HDU

题目大意:给出一个N*M的迷宫,迷宫中有一扇门D,只有在T时刻会打开,现在你0时刻位于S,你需要在正好在T时刻到达D,你只能上下左右移动,每次移动耗费1时刻,且同一个位置不能进入两次,问是否能在T时刻刚好到达D处。

范围 1 < N,M < 7, 1 < T < 50,这个范围有点大,直接DFS回溯搜会TLE,我们要加上一个剪枝,这个剪枝十分重要,我们求出起点到终点的距离(横向距离 + 纵向距离),若这个距离为奇数,则时间T必须也要为奇数,否则时间T必须为偶数(其中的道理显而易见),只有这样,你才有可能在T时刻到达D。详情见下面的代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <queue>
 7 #include <stack>
 8 using namespace std;
 9 
10 typedef long long LL;
11 typedef unsigned long long ULL;
12 const int dx[] = {1,-1,0,0};
13 const int dy[] = {0,0,1,-1};
14 
15 int N, M, T, bx, by, ex, ey;
16 char Map[10][10];
17 int vis[10][10];
18 
19 bool dfs(int x, int y, int t){
20     if(x == ex && y == ey && t == T) return true;
21     if(t >= T) return false;
22     for(int i = 0; i < 4; ++i){
23         int nx = x + dx[i];
24         int ny = y + dy[i];
25         if(nx >= 0 && ny >= 0 && nx < N && ny < M){
26             if(vis[nx][ny]) continue;
27             if(Map[nx][ny] == 'X') continue;
28             vis[nx][ny] = 1;
29             if(dfs(nx, ny, t+1)) return true;
30             vis[nx][ny] = 0;
31         }
32     }
33     return false;
34 }
35 
36 int main(){
37     while(scanf("%d%d%d", &N, &M, &T) == 3 && N){
38         for(int i = 0; i < N; ++i){
39             scanf("%s", Map[i]);
40             for(int j = 0; j < M; ++j)
41                 if(Map[i][j] == 'D') {
42                     ex = i;
43                     ey = j;
44                 }else if(Map[i][j] == 'S') {
45                     bx = i;
46                     by = j;
47                 }
48         }
49 
50         //奇偶剪枝
51         int dis = abs(bx-ex)+abs(by-ey);
52         if(dis%2 != T%2) {
53             printf("NO
");
54             continue;
55         }
56 
57         memset(vis, 0, sizeof(vis));
58         vis[bx][by] = 1;
59         if(dfs(bx, by, 0)) printf("YES
");
60         else printf("NO
");
61     }
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/DynastySun/p/9436456.html