学习链接:http://www.ihypo.net/1554.html
https://www.slyar.com/blog/depth-first-search-even-odd-pruning.html
http://blog.csdn.net/chyshnu/article/details/6171758
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
题解:刚开始写直接超时,还没学剪枝,奇偶剪枝...
关于奇偶剪枝
首先举个例子,有如下4*4的迷宫,'.'为可走路段,'X'为障碍不可通过
S...
....
....
...D
从S到D的最短距离为两点横坐标差的绝对值+两点纵坐标差的绝对值 = abs(Sx - Dx) + abs(Sy - Dy) = 6,这个应该是显而易见的。
遇到有障碍的时候呢
S.XX
X.XX
...X
...D
你会发现不管你怎么绕路,最后从S到达D的距离都是最短距离+一个偶数,这个是可以证明的
而我们知道:
奇数 + 偶数 = 奇数
偶数 + 偶数 = 偶数
因此不管有多少障碍,不管绕多少路,只要能到达目的地,走过的距离必然是跟最短距离的奇偶性是一致的。
所以如果我们知道从S到D的最短距离为奇数,那么当且仅当给定的步数T为奇数时,才有可能走到。如果给定的T的奇偶性与最短距离的奇偶性不一致,那么我们就可以直接判定这条路线永远不可达了。
这里还有个小技巧,我们可以使用按位与运算来简化奇偶性的判断。我们知道1的二进制是1,而奇数的二进制最后一位一定是1,而偶数的二进制最后一位一定是0。所以如果数字&1的结果为1,那么数字为奇数,反之为偶数。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <limits.h> 5 #include <algorithm> 6 #include <iostream> 7 #include <ctype.h> 8 #include <iomanip> 9 #include <queue> 10 #include <stdlib.h> 11 using namespace std; 12 13 char map[10][10]; 14 int flag, Xnum, Sx, Sy, Dx, Dy; 15 int n, m, t; 16 int dx[4] = {0,0,1,-1}; 17 int dy[4] = {1,-1,0,0}; 18 19 void DFS(int x, int y, int time) 20 { 21 if (x<=0 || x>n || y<=0 || y>m) return; 22 if (flag == 1) return; 23 if (x == Dx && y == Dy && time == t) 24 { 25 if(time == t) 26 flag = 1; 27 return; 28 } 29 30 int temp=t-time-abs(x-Dx)-abs(y-Dy); 31 if(temp<0||temp%2) return ; 32 33 for (int i = 0; i<4; i++) 34 { 35 int x1 = x + dx[i]; 36 int y1 = y + dy[i]; 37 if (map[x1][y1] != 'X') 38 { 39 map[x1][y1] = 'X'; 40 DFS(x1, y1, time + 1); 41 map[x1][y1] = '.'; 42 } 43 } 44 return; 45 } 46 47 48 int main() 49 { 50 while (cin>>n>>m>>t) 51 { 52 if(n==0&&m==0&&t==0) break; 53 Xnum = 0; 54 for (int i = 1; i<=n; i++) 55 { 56 for (int j = 1; j<=m; j++) 57 { 58 cin>>map[i][j]; 59 if (map[i][j] == 'S') 60 { 61 Sx = i; 62 Sy = j; 63 } 64 if (map[i][j] == 'D') 65 { 66 Dx = i; 67 Dy = j; 68 } 69 if (map[i][j] == 'X') 70 Xnum ++; 71 } 72 } 73 flag = 0; 74 map[Sx][Sy] = 'X'; 75 76 if(n*m-Xnum<=t){ 77 cout<<"NO"<<endl; 78 continue; 79 } 80 DFS(Sx, Sy, 0); 81 if (flag) 82 cout<<"YES"<<endl; 83 else 84 cout<<"NO"<<endl; 85 } 86 return 0; 87 }