本题链接:点击打开链接
Tempter of the Bone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 120103 Accepted Submission(s): 32447
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
Author
ZHANG, Zheng
Source
Recommend
其中:
'X':表示墙,狗不能进入;
'S':表示狗的起始位置;
'D':表示大门;
'.' :表示狗能走的路。
解题思路:一看题意就知道是一道搜索得题,果断用深搜,但很可惜,超时也很果断!然后网上查找了一些剪枝方法,慢慢的剪枝,总算剪枝到92MS AC。
剪枝方法1:如果可以走的地板数目小于给定的时间,那么绝对不可能得逃出。
剪枝方法2:还有就是狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门,也不可能得逃出。
剪掉这两种情况后,就用深度搜索来做。从起点出发,深搜周围的路,走过的路就更新为墙,一直搜索下去,如果是一条“死路“”就回溯,把可能的路都搜索一遍过去,看看是否有“活路”。
这最用到最主要的剪枝方法就是奇偶剪枝,也简单介绍下:
可以把地图看成这样:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
不难看出:
从任意 0 走到任意 1 或从任意1到任意0始终是奇数步;
从任意 0 走到任意 0 或从任意1到任意1始终是偶数步;
结论(对于此题):
所以当遇到从 0 走向 0 但是要求时间是奇数的,或者,
从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可能到达。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
char mp[10][10];
int n,m,t;
int dir[4][2]= {{0,1},{1,0},{-1,0},{0,-1}};
int sx,sy,ex,ey; //sx,sy为起点 ex,ey为大门
bool flag;
void dfs(int x,int y,int tk)
{
int nx,ny;
if(flag) //找到"活路"及时退出
return;
if(tk>t)
return;
if((t-tk-abs(x-ex)-abs(y-ey))%2==1) //奇偶剪枝
return;
if(x==ex&&y==ey&&tk==t) //找到活路
{
flag=true;
return;
}
for(int i=0; i<4; i++)
{
nx=x+dir[i][0];
ny=y+dir[i][1];
if(mp[nx][ny]!='X'&&nx>=0&&ny>=0&&nx<n&&ny<m)
{
mp[nx][ny]='X';
dfs(nx,ny,tk+1);
mp[nx][ny]='.'; //回溯
if(flag) //找到"活路"及时退出
return;
}
}
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&t)&&(n+m+t))
{
int w=0;
memset(mp,'X',sizeof(mp));
for(int i=0; i<n; i++)
scanf("%s",mp[i]);
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(mp[i][j]=='S')
{
sx=i;
sy=j;
mp[sx][sy]='X';
}
if(mp[i][j]=='D')
{
ex=i;
ey=j;
}
if(mp[i][j]=='X')
w++; //统计墙的数量
}
if(n*m-w<t||(t-abs(sx-ex)-abs(sy-ey))%2==1||abs(sx-ex)+abs(sy-ey)>t) //可走方块是否比时间少,最短时间是否比t大,奇偶剪枝
{
printf("NO\n");
continue;
}
flag=false;
dfs(sx,sy,0);
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}