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.
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.
'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
NO YES
大概题意:
给出地图大小M,N规定时间T以及地图,从S走到D,要求每个地方只能走一次且耗时1s,'X'表示此路不通,要求在 第 T 秒到达D点。
如果能够办到输出YES不能输出NO。
样例:
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
char map[101][101];
int n,m,a[4][2]={0,1,0,-1,1,0,-1,0},endx,endy,t,book;
void dfs(int x,int y,int step) //三大剪枝.
{
int tx,ty,i;
if(book==1||step>t) //1.当已经找到路或者超过时间剪去
return;
int c=abs(x-endx)+abs(y-endy); //c表示当前位置到终点的理想最短时间.
if(c+step>t) //2.加上理想最短时间还是超时那么就剪去
return;
if((c+t-step)%2==1) //3.奇偶剪枝(下面有具体解释)
return ;
if(x==endx&&y==endy&&step==t) //当找到路就标记为1.
{
book=1;
return;
}
for(i=0;i<4;i++) //枚举4个方向.
{
tx=x+a[i][0];
ty=y+a[i][1];
if(tx<0||tx>=n||ty<0||ty>=m||map[tx][ty]=='X')
continue;
map[tx][ty]='X';
dfs(tx,ty,step+1);
map[tx][ty]='.';
}
}
int main()
{
int i,j,startx,starty;
while(scanf("%d%d%d",&n,&m,&t)&&m)
{
for(i=0;i<n;i++)
scanf("%s",map[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(map[i][j]=='D')
endx=i,endy=j;
if(map[i][j]=='S')
startx=i,starty=j;
}
book=0;
map[startx][starty]='X';
dfs(startx,starty,0);
if(book==1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
由于这道题是要求的是在某个时间点到达规定地方,并非最短路程问题,所以不能使用简单的广度搜索
(简单的广度搜索visit标记数组,使得队列中每个点的步数都是起点到该点的最短路程.如果不加入visit数组进行标记那么就会发生死循环.)
所以应该使用深度搜索
对于奇偶剪枝:
假设当前为x,y,终点tx,ty.那么x,y到tx,ty的有效方向一定是一个或者两个(当两个点在同一排或者同一列的时候有效方向为一个)
那么接下来的无效步数(注意:不是无效方向,而是无效步数)一定是偶数.
在上幅图中第3,5,6,8便是无效步数.其意思就是有一步背离了有效方向,那么就有对应的一步走回来.所以是偶数