1. 程式人生 > >hdu1010 Tempter of the Bone---DFS+奇偶剪枝

hdu1010 Tempter of the Bone---DFS+奇偶剪枝

div 其他 xxx ace 沒有 不可 get problem 個數

題目鏈接:

http://acm.hdu.edu.cn/showproblem.php?pid=1010

題目描述:
根據地圖,‘S‘為開始位置,‘D‘為門的位置,‘ . ‘為空地,‘X‘為墻,不能經過,問:在指定的時間,是否能到達‘門‘的位置。註意:路不可以重復經過,時間也要剛好是 t ,不能少.

思路:

此處不能用BFS,因為時間要恰好為t,還是得用DFS,不過需要剪枝才能過。

奇偶剪枝:

從一個點到達另外一個點的最短路徑長度(時間)可以根據兩點坐標求出,路徑長度(非最短)與最短路徑的長度同奇偶,它們的差一定是偶數!舉個例子,就像兩個偶數的差差是偶數,兩個個數的差也是偶數.

此處還有一個剪枝:
設墻的數目為wall,如果wall + t >= n * m,一定到達不了,因為大於號顯然成立,這裏主要討論等號的情況。

比如下圖

3 3 1

SDX

XXX

XXX

只需要一步就可以到達,此時wall = 7, t = 1,wall + t < n * m,有可行解,這是由於有S,D的存在,所以如果有可行解,wall的數目一定會比n*m-t要小,等於的話是沒有可行解的。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<string>
 6 #include<queue>
 7 using
namespace std; 8 typedef long long ll; 9 const int INF = 1<<30; 10 const int maxn = 100000; 11 int T, cases; 12 int n, m, k, x1, y1, x2, y2; 13 char Map[10][10]; 14 int dir[4][2] = {0,1,1,0,-1,0,0,-1}; 15 bool dfs(int x, int y, int time)//到x1, y1點,花費時間time 16 { 17 if(x < 0 || x >= n || y < 0 || y >= m || time > k)return
false; 18 //剪枝 19 if(time == k && x == x2 && y == y2)return true; 20 int mintime = k - time - abs(x - x2) - abs(y - y2); 21 if(mintime < 0)return false;//最優性剪枝,當前沿著最優路徑走,還是會超過k秒,返回假 22 if(mintime & 1)return false;//奇偶剪枝,相減的時間是奇數的話,在k秒的時候一定到不了終點 23 24 for(int i = 0; i < 4; i++) 25 { 26 int xx = x + dir[i][0]; 27 int yy = y + dir[i][1]; 28 if(Map[xx][yy] != X) 29 { 30 Map[xx][yy] = X; 31 if(dfs(xx, yy, time + 1))return true; 32 Map[xx][yy] = .; 33 } 34 } 35 return false; 36 } 37 int main() 38 { 39 while(cin >> n >> m >> k && (n + m + k)) 40 { 41 int wall = 0; 42 for(int i = 0; i < n; i++) 43 { 44 cin >> Map[i]; 45 for(int j = 0; j < m; j++) 46 { 47 if(Map[i][j] == S)x1 = i, y1 = j; 48 else if(Map[i][j] == D)x2 = i, y2 = j; 49 else if(Map[i][j] == X)wall++; 50 } 51 } 52 if(wall + k >= n * m) 53 ///這裏是一個特別好的剪枝,如果墻的數目+步數>=n*m,一定不可能完成任務 54 ///重點考慮等號,除了墻還有‘S‘和‘D‘,墻的數目最多為n*m-k-1(距離,比如k = 1時,S和D相鄰,其他都是墻,此時墻的數目最多為n*m-2,滿足上述式子) 55 { 56 printf("NO\n"); 57 continue; 58 } 59 Map[x1][y1] = X;//先設置成X表示該點不能再經過 60 if(dfs(x1, y1, 0))printf("YES\n"); 61 else printf("NO\n"); 62 } 63 }

hdu1010 Tempter of the Bone---DFS+奇偶剪枝