Tempter of the Bone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 97157 Accepted Submission(s): 26364
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.
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
这个题真是弄了快一天了,刚刚看了BFS,看到有这么一道题,就尝试做,才发现不是BFS,因为题目是T时刻恰好到达,而不是T时刻内到达,也就说不是求迷宫最短距离。
方法:
1.DFS,输入注意不要用gets,因为这个也错了很多次,用scanf读或者getchar读都可以!
2.写个bool ok变量,这个作为结果,如果dfs恰好T时间内到达就ok为true,否则为false,先把起点和终点记录下来。来调用dfs函数。调用时因为是次数限制,所以DFS函数多加一个参数,int step,注意是一个点只能走一次,所以可以开一个数组way[maxn][maxn],0,1来记录是否走过!这是个技巧!
3.在dfs函数内,结束条件是step > t或者已经ok了!
4.ok=true结束的条件是,当前的x ,y是终点坐标,并且step == t,
注意:这样写完会超时,要用奇偶剪枝:
结论编辑
推广之,若 t-[abs(ex-sx)+abs(ey-sy)] 结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
详细百度即可!
当然剪枝放在外面也行,这个题数据可能比较巧。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,m,t,sx,sy,gx,gy,ok;
const int maxn = 100+10;
int way[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
char mep[maxn][maxn];
void dfs(int x,int y,int step){
if ((t-step-abs(gx-x)-abs(gy-y)) % 2)return;
if (ok || step > t)return;
if (step == t && x == gx && y == gy){
ok = true;
return;
}
for (int i = 0; i < 4; ++i){
int nx = dx[i] + x;
int ny = dy[i] + y;
if (nx > -1 && ny > -1 && nx < n && ny < m && !way[nx][ny] && mep[nx][ny] != 'X'){
way[nx][ny] = 1;
dfs(nx,ny,step+1);
way[nx][ny] = 0;
}
}
}
int main()
{
while(cin >> n >> m >> t && (n || m || t)){
ok=false;
memset(way,0,sizeof(way));
memset(mep,0,sizeof(mep));
for (int i = 0; i < n; ++i){
scanf("%s",mep[i]);
for (int j = 0; j < m; ++j){
if (mep[i][j] == 'S'){
sx = i;
sy = j;
}
if (mep[i][j] == 'D'){
gx = i;
gy = j;
}
}
}
way[sx][sy]=1;
dfs(sx,sy,0);
if (ok)cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}