标签:
深搜(dfs)就是一條路搜到底再回溯的過程,不像廣搜那樣一層一層地搜,一般用於找一條符合的路徑就ok了,而不用找到最短的路;
今天做了一題很典型的深搜的題目,雖然之前做過挺多的,但是都沒有怎麼總結,寫起來不夠快...
其實總結起來還是有一個大概的框架的:
這題就是找到一條路徑能夠遍歷所有格子的,但是要輸出字典序最小的一個序列,想想廣搜的話,好像不能保存一條路徑,深搜則挺合理的~
這題還是想了很多:
1.
我本來的想法是每個格子都需要作為起點搜一遍,這樣耗時會比較大,但是也可以一旦找到了,就跳出所有循環,這樣就可以保證不超時,
所以現在總結起來一直超時的原因可能就是找到後沒有跳出..還要注意找到後也要跳出深搜的遞歸,加個判斷就可以了,所以總結起來就是:
加個flag標誌是否已經找到一條路徑~
然後記錄路徑的方式就是加一個深度的參數cur,每次把點放到數組a[cur],最後滿了就數組a[]就行了!!!
initial flag = 0;
dfs:
if find a path:
print();
flag = 1;
a[cur] = now_point;
for i = 1 to 8:
find next position pi;
if !vis && valid() && !flag
vis(pi) = 1;
dfs(pi);
vis(pi) = 0;
2.
當然還有另一個問題,就是如何保證字典序最小呢???
我一開始用一個vector <point> v 先八個方向存起來,就是next position;然後根據字典序排序,從小到大開始深搜,但是之前錯了幾次,
也不知道是不是因為這個,但是我覺得還是挺合理的...
然後看了別人說是為了字典序,所以要保證走的順序,就是找next position的時候,要先找小的,再找大的,準確來說就是如下圖的順序:
3.
最後的最後,我覺得很奇怪的就是只從A1開始搜索,就可以過這題,而不需要每一個格子都作為起點搜一邊,這是我覺得很奇怪的地方,
我覺得這樣應該是不對的,也許是跟測試數據有關?幷不懂...
最後上代碼:
1 // poj 2488.A Knight‘s Journey 2 // dfs + 字典序 3 // http://blog.csdn.net/lyy289065406/article/details/6647666 4 // http://www.cnblogs.com/rainydays/archive/2011/05/22/2053574.html 5 #include <iostream> 6 #include <cstdio> 7 #include <cstring> 8 #include <algorithm> 9 #include <vector> 10 11 using namespace std; 12 13 const int N = 30; 14 15 struct point { 16 int x; 17 int y; 18 }a[N]; 19 20 bool vis[N][N]; 21 int n, m; 22 int move_x[] = {-1, 1, -2, 2, -2, 2, -1, 1}; //注意方向顺序 23 int move_y[] = {-2, -2, -1,-1, 1, 1, 2, 2}; 24 bool flag; 25 26 void dfs(int x, int y, int cur) 27 { 28 if(cur == n * m - 1) //從0開始就要減1 29 { 30 for(int i=0; i<cur; i++) 31 printf("%c%d", a[i].y - 1 + ‘A‘, a[i].x); 32 printf("%c%d\n", y - 1 + ‘A‘, x); 33 flag = 1; 34 } 35 a[cur].x = x; //记录路径 36 a[cur].y = y; 37 for(int i=0; i<8; i++) 38 { 39 point temp; 40 temp.x = x + move_x[i]; 41 temp.y = y + move_y[i]; 42 if(!vis[temp.x][temp.y] && temp.x >=1 && temp.x <= n && temp.y >=1 && temp.y <=m && !flag) 43 { 44 vis[temp.x][temp.y] = 1; 45 dfs(temp.x, temp.y, cur + 1); 46 vis[temp.x][temp.y] = 0; 47 } 48 } 49 } 50 51 int main() 52 { 53 int k=1; 54 int t; 55 scanf("%d", &t); 56 while(t--) 57 { 58 flag = 0; 59 memset(vis, 0, sizeof(vis)); 60 scanf("%d%d", &n, &m); 61 printf("Scenario #%d:\n", k++); 62 /*for(int i=1; i<=n; i++) //暴搜 63 { 64 for(int j=1; j<=m; j++) 65 { 66 67 vis[i][j] = 1; //标记起点 68 dfs(i, j, 0); 69 if(flag) 70 break; 71 vis[i][j] = 0; 72 } 73 if(flag) 74 break; 75 }*/ 76 vis[1][1] = 1; //这样也能ac 77 dfs(1, 1, 0); 78 if(!flag) 79 printf("impossible\n"); 80 printf("\n"); 81 } 82 return 0; 83 }
标签:
原文地址:http://www.cnblogs.com/dominjune/p/4724501.html