1. 程式人生 > >【2018.07.29】(搜索)學習DFS算法小記

【2018.07.29】(搜索)學習DFS算法小記

block win each 例題 show csdn assume urn n+1

參考網站:https://blog.csdn.net/ldx19980108/article/details/76324307

這個算法還算好理解一點吧,有遞歸的思路,理解了一個上午~

感覺還不錯,看完代碼基本上就懂了,可以自己實現了

/*     Fire Net     */
/*Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall.
A blockhouse is a small castle that has four openings through which to shoot. The four openings are facing North, East, South, and West, respectively. There will be one machine gun shooting through each opening.
Here we assume that a bullet is so powerful that it can run across any distance and destroy a blockhouse on its way. On the other hand, a wall is so strongly built that can stop the bullets.
The goal is to place as many blockhouses in a city as possible so that no two can destroy each other. A configuration of blockhouses is legal provided that no two blockhouses are on the same horizontal row or vertical column in a map unless there is at least one wall separating them. In this problem we will consider small square cities (at most 4x4) that contain walls through which bullets cannot run through.
The following image shows five pictures of the same board. The first picture is the empty board, the second and third pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the maximum number of blockhouses in a legal configuration is 5; the second picture shows one way to do it, but there are several other ways.
Your task is to write a program that, given a description of a map, calculates the maximum number of blockhouses that can be placed in the city in a legal configuration.
The input file contains one or more map descriptions, followed by a line containing the number 0 that signals the end of the file. Each map description begins with a line containing a positive integer n that is the size of the city; n will be at most 4. The next n lines each describe one row of the map, with a ‘.‘ indicating an open space and an uppercase ‘X‘ indicating a wall. There are no spaces in the input file.
For each test case, output one line containing the maximum number of blockhouses that can be placed in the city in a legal configuration.

Sample input:
4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0

Sample output:
5
1
5
2
4
*/ #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; /*拿到這道題目,我肯定是不會的啦,所以我去擺渡了一下具體實現方法,用到的是dfs算 法,簡單看了例題,需要用到的是遍歷整個數組。按照這個思維模式的話,我覺得這道題 也可以用遞歸的方法做*/ //先測試一下輸入會不會出錯 /*有地圖就會有二維數據,但記錄step的時候依舊要使用單個數字,這時候縱坐標X=step/ len+1,橫坐標Y=step%len+1,如果二維地圖是從(1,1)開始輸入的話
*/ char a[5][5]; int Count,len; int judge( int x , int y) { int i; //判斷上面有沒有碉堡或者墻壁,此時的Y大小不變 for ( i=x-1 ; i>0 ; i-- ) { if ( a[i][y] == O ) return 0;//上面有堡壘了,不滿足,退出函數 if ( a[i][y] == X ) break;//上面有墻壁了,滿足,跳出循環 } //判斷左邊有沒有碉堡或者墻壁,此時的X大小不變 for ( i=y-1 ; i>0
; i-- ) { if ( a[x][i] == O ) return 0;//左邊有堡壘了,不滿足,退出函數 if ( a[x][i] == X ) break;//左邊有墻壁了,滿足,跳出循環 } return 1;//上面條件兩者皆滿足,該點滿足條件,返回1 } void dfs(int step, int num )//step是當前位置,num是在這個分支下最大的count { if ( step==len*len ) //如果發現這時候達到了上限,要開始回溯到上個岔路口 { if ( num > Count ) Count=num;//如果這種情況下碉堡比較多的話替換 return; } int x=step/len+1 ,y=step%len+1;//數字向二維坐標轉換,這裏是從(1,1)開始輸入的 if ( a[x][y]==. && judge(x,y) )//如果這個點是個空地的話,且前面沒碉堡的話 { a[x][y]=O;//標記作用,將這個點替換成碉堡 dfs( step+1 , num+1 );//向著下一個點前進 a[x][y]=.;//變回空地,為了回溯時候可以恢復岔路口的初始狀態 } dfs( step+1 , num );//不管上面的這句if條件滿不滿足,都要進入下一句的判斷 } int main(void) { int i, j, count; while ( scanf("%d", &len) , len ) { for ( i=1 ; i<=len ; i++ ) { getchar(); for ( j=1 ; j<=len ; j++ ) { scanf("%c", &a[i][j] ); } //getchar(); getchar不能放這裏,會導致第一個字符會是回車(剛輸完數字時) } /*輸入測試for ( i=1 ; i<=len ; i++ ) { for ( j=1 ; j<=len ; j++ ) { printf("%c", a[i][j] ); } }*/ Count=0; dfs(0,0); cout<<Count<<endl; } return 0; }

【2018.07.29】(搜索)學習DFS算法小記