hdu1010 Tempter of the Bone---DFS+奇偶剪枝
阿新 • • 發佈:2018-03-30
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 usingnamespace 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)returnfalse; 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+奇偶剪枝