hdu Tempter of the Bone (奇偶剪枝)

学习链接: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 }
原文地址:https://www.cnblogs.com/wangmengmeng/p/5099182.html