hdu1010:Tempter of the Bone 搜索+剪枝
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
转自:http://www.cnblogs.com/zhourongqing/archive/2012/04/28/2475684.html
2017 5 15
果然之前理解不到位,dfs回溯还是有套路的啊,更新一下代码。
深度优先搜索,用到了奇偶剪枝,第一次听说。。仍然是咸鱼一条
奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
刚开始也是写了宽搜,结果wa,看题,提取关键字!
代码:
1 #define _CRT_SECURE_NO_WARNINGS
2 #include <functional>
3 #include <algorithm>
4 #include <iostream>
5 #include <cstring>
6 #include <cassert>
7 #include <cstdio>
8 #include <cctype>
9 #include <vector>
10 #include <string>
11 #include <queue>
12 #include <stack>
13 #include <cmath>
14 #include <map>
15 #include <set>
16 using namespace std;
17 #define rep(i,a,n) for (int i=a;i<n;i++)
18 #define per(i,a,n) for (int i=n-1;i>=a;i--)
19 #define pb push_back
20 #define mp make_pair
21 #define all(x) (x).begin(),(x).end()
22 #define fi first
23 #define se second
24 #define SZ(x) ((int)(x).size())
25 typedef vector<int> VI;
26 typedef long long ll;
27 typedef pair<int, int> PII;
28 const ll mod = 1000000007;
29 ll powmod(ll a, ll b) { ll res = 1; a %= mod; assert(b >= 0); for (; b; b >>= 1) { if (b & 1)res = res*a%mod; a = a*a%mod; }return res; }
30 // head
31 const int inf = 0x3f3f3f3f;
32 #define maxn 10
33 const int iadd[] = {0, 1, 0, -1}, jadd[] = {1, 0, -1, 0};
34 char maze[maxn][maxn];
35 int T, sposi, sposj, dposi, dposj, n, m;
36 int vis[maxn][maxn], step = 0;
37 bool flag = false;
38
39 int dfs(int si, int sj){
40 if(si == dposi && sj == dposj){
41 if(step == T)
42 flag = true;
43 return 0;
44 }
45
46 int tmp1 = abs(dposi - si) + abs(dposj - sj);
47 int tmp2 = abs(T - step);
48 tmp1 &= 1; tmp2 &= 1;
49 if(tmp1 != tmp2){
50 return 0;
51 }
52
53 for(int i = 0; i < 4; i++){
54 int nexti = si + iadd[i];
55 int nextj = sj + jadd[i];
56 if(nexti < 0 || nexti >= n || nextj < 0 || nextj >= m)
57 continue;
58 if(vis[nexti][nextj] || maze[nexti][nextj] == 'X')
59 continue;
60 step++;
61 vis[nexti][nextj] = 1;
62 dfs(nexti, nextj);
63 step--;
64 vis[nexti][nextj] = 0;
65 if(flag)
66 break;
67 }
68 return 0;
69 }
70
71 int main(){
72 while(scanf("%d %d %d", &n, &m, &T) && n){
73 memset(vis, 0, sizeof(vis));
74 memset(maze, 0, sizeof(maze));
75 step = 0; flag = false;
76 for(int i = 0; i < n; i++){
77 for(int j = 0; j < m; j++){
78 scanf(" %c", &maze[i][j]);
79 if(maze[i][j] == 'S'){
80 sposi = i, sposj = j;
81 }
82 if(maze[i][j] == 'D'){
83 dposi = i, dposj = j;
84 }
85 }
86 }
87 vis[sposi][sposj] = 1;
88 dfs(sposi, sposj);
89 if(flag){
90 printf("YES\n");
91 }
92 else{
93 printf("NO\n");
94 }
95 }
96 }