题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
思路:
题目思路很清晰,一眼能看出用DFS来做,难点在于如果不剪枝就会超时。
这题对我来说最大的收获就是了解了奇偶剪枝。
奇偶剪枝理解:
在一个矩阵中,设起点为(a, b),终点为(c, d)。则最短路min为abs(a-c)+abs(b-d),
画图总结规律可以得出任意一条路径x,x-min必定为偶数。
我自己对这种思想抽象理解为,若有1步不走在最短路上,则必定还需要1步走回最短路,因此必定多出2步。
下面贴出AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 int n, m, t, flag = 0, vis[10][10]; 8 char maze[10][10]; 9 10 void dfs(int i, int j, int cur){ 11 if (flag||cur > t) return; 12 if (maze[i][j] == 'X'||maze[i][j] == '#') return; 13 if (cur < t&&maze[i][j] == 'D') return; 14 if (cur == t&&maze[i][j] == 'D'){ 15 flag = 1; 16 return; 17 } 18 else{ 19 if (!vis[i][j]){ 20 vis[i][j] = 1; 21 dfs(i+1, j, cur+1); 22 dfs(i-1, j, cur+1); 23 dfs(i, j+1, cur+1); 24 dfs(i, j-1, cur+1); 25 vis[i][j] = 0; 26 } 27 } 28 } 29 30 int main() 31 { 32 //freopen("E://input.txt", "r", stdin); 33 while(cin>>n>>m>>t){ 34 if(!n&&!m&&!t) break; 35 for (int i = 0; i < 10; i++) 36 for (int j = 0; j < 10; j++) 37 maze[i][j] = '#'; 38 int sx, sy, dx, dy, cnt = 0; 39 for (int i = 1; i <= n; i++) 40 for (int j = 1; j <= m; j++){ 41 cin>>maze[i][j]; 42 if (maze[i][j] == 'S'){ 43 sx = i; 44 sy = j; 45 } 46 if (maze[i][j] == 'D'){ 47 dx = i; 48 dy = j; 49 } 50 if (maze[i][j] == 'X') cnt++; 51 } 52 /*可走步数小于t必然不行*/ 53 if (m*n - cnt < t){ 54 cout<<"NO"<<endl; 55 continue; 56 } 57 /*奇偶剪枝*/ 58 int minsum = abs(sx-dx)+abs(sy-dy); 59 if ((t - minsum)%2 != 0){ 60 cout<<"NO"<<endl; 61 continue; 62 } 63 dfs(sx, sy, 0); 64 if (flag) cout<<"YES"<<endl; 65 else cout<<"NO"<<endl; 66 flag = 0; 67 memset(maze, 0, sizeof(maze)); 68 memset(vis, 0, sizeof(vis)); 69 } 70 71 return 0; 72 }