Tempter of the Bone(DFS+剪枝)

简介: Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking.

Problem Description

The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.

Input

The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.

The input is terminated with three 0's. This test case is not to be processed.

Output

For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.

SampleInput

4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0

SampleOutput

NO
YES

最开始看见这题直接看了样例,以为就是询问t时间内能不能走出去,直接写了个BFS过了样例,提交上去WA了=7=,事实证明还是不能偷懒。
题意就是S当前位置,D是门,X是墙,问你能不能刚好在t时刻走到门D那里。
然后就是套DFS,本地测试炸栈,就想到了剪枝一下
1 int tp = t - step - abs(dx - x) - abs(dy - y);
2 if(tp < 0 || tp % 2 == 1)
3     return ;

这就是剪枝代码,dx和dy代表门的坐标,x、y为当前坐标,step表示以及走了的步数。

当剩余时间走不到门时结束,这个好理解,难理解的是为什么为奇数是也结束。

因为从s每走一步,一定是x或y进行+1或者-1,要使得t时间刚好走到门d。

最短路径m = |dx - x| + |dy - y|;

两种情况,t < m时,肯定无法到达;

t >= m时,从S到D的行走步骤两部分组成,step = t = m + x;(m为最段路径,x为附加步数);

这x = t - m步一定是从最短路径中的某一步走出去,再回到最短路径的步数,而且二者一定是相等的。

如图,最短路径为橘色所示,附加路径为蓝色所示,把蓝色路径分为走出和走回两部分,无论你怎么添加附加路径,这两部分一定是相等的步数。

所以,x一定得为偶数才能保证从S刚好走到D。

而在剪枝中,tp就是我们的x,只有当tp为偶数时,才继续行走。

完整代码:

  1 #include <iostream>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <sstream>
  6 #include <iomanip>
  7 #include <map>
  8 #include <stack>
  9 #include <deque>
 10 #include <queue>
 11 #include <vector>
 12 #include <set>
 13 #include <list>
 14 #include <cstring>
 15 #include <cctype>
 16 #include <algorithm>
 17 #include <iterator>
 18 #include <cmath>
 19 #include <bitset>
 20 #include <ctime>
 21 #include <fstream>
 22 #include <limits.h>
 23 #include <numeric>
 24 
 25 using namespace std;
 26 
 27 #define F first
 28 #define S second
 29 #define mian main
 30 #define ture true
 31 
 32 #define MAXN 1000000+5
 33 #define MOD 1000000007
 34 #define PI (acos(-1.0))
 35 #define EPS 1e-6
 36 #define MMT(s) memset(s, 0, sizeof s)
 37 typedef unsigned long long ull;
 38 typedef long long ll;
 39 typedef double db;
 40 typedef long double ldb;
 41 typedef stringstream sstm;
 42 const int INF = 0x3f3f3f3f;
 43 
 44 int n,m,t,flag,wall;
 45 int sx,sy,dx,dy;
 46 char mp[8][8];
 47 int vis[8][8];
 48 int fx[4][2] = {1,0,-1,0,0,1,0,-1};
 49 
 50 bool check(int x,int y){
 51     if(!vis[x][y] && mp[x][y] != 'X' && x >= 0 && y >= 0 && x < n && y < m){
 52         return true;
 53     }
 54     return false;
 55 }
 56 
 57 void dfs(int x,int y,int step){
 58     if(flag)
 59         return ;
 60     if(x == dx && y== dy && step == t){
 61         flag = 1;
 62         return ;
 63     }
 64 
 65     int tp = t - step - abs(dx - x) - abs(dy - y);
 66     if(tp < 0 || tp % 2 == 1)
 67         return ;
 68 
 69     for(int i = 0; i < 4; i++){
 70         int next_x = x + fx[i][0];
 71         int next_y = y + fx[i][1];
 72         if(check(next_x,next_y)){
 73             vis[next_x][next_y] = 1;
 74             dfs(next_x,next_y,step+1);
 75             if(flag)
 76                 return ;
 77             vis[next_x][next_y] = 0;
 78         }
 79     }
 80     return ;
 81 }
 82 
 83 int main(){
 84     ios_base::sync_with_stdio(false);
 85     cout.tie(0);
 86     cin.tie(0);
 87     while(cin>>n>>m>>t && n && m && t){
 88         fill(vis[0],vis[0]+64,0);
 89         MMT(mp);
 90         flag = 0, wall = 0;
 91         for(int i = 0; i < n; i++)
 92             cin>>mp[i];
 93         for(int i = 0; i < n; i++){
 94             for(int j = 0; j < m; j++){
 95                 if(mp[i][j] == 'S')
 96                     sx = i,sy = j;
 97                 if(mp[i][j] == 'D')
 98                     dx = i,dy = j;
 99                 if(mp[i][j] == 'X')
100                     wall++;
101             }
102         }
103         if(t < abs(dx - sx) + abs(dy - sy) || t > n*m - wall - 1){
104             cout << "NO" << endl;
105             continue;
106         }
107         vis[sx][sy] = 1;
108         dfs(sx,sy,0);
109         if(flag)
110             cout << "YES" << endl;
111         else
112             cout << "NO" << endl;
113     }
114 
115     return 0;
116 }

 

 

目录
相关文章
|
6月前
生日蛋糕(dfs剪枝)
生日蛋糕(dfs剪枝)
42 0
|
12月前
|
C++
DFS之剪枝与优化
DFS之剪枝与优化
72 0
|
6月前
E. Nearest Opposite Parity(多源最短路bfs)
E. Nearest Opposite Parity(多源最短路bfs)
|
算法
1091 zoj Knight Moves的BFS算法和DFS
1091 zoj Knight Moves的BFS算法和DFS
56 0
Biggest Number (DFS+剪枝)
Biggest Number (DFS+剪枝)
37 0
CF1272 E.Nearest Opposite Parity(反向建图+BFS)
CF1272 E.Nearest Opposite Parity(反向建图+BFS)
103 0
CF1272 E.Nearest Opposite Parity(反向建图+BFS)
|
机器学习/深度学习 测试技术
DFS之剪枝
笔记
74 0
DFS之剪枝
|
vr&ar
DFS之剪枝与优化(二)
AcWing 167. 木棒
137 1
DFS之剪枝与优化(二)
CF191C——Fools and Roads(树上边差分+LCA)
CF191C——Fools and Roads(树上边差分+LCA)
125 0