小明做了一个很久很久的梦,醒来后他竟发现自己和朋友在一个摇摇欲坠的大棋盘上,他们必须得想尽一切办法逃离这里。
经过长时间的打探,小明发现,自己所在的棋盘格子上有个机关,上面写着“你只有一次机会,出发后t秒大门会为你敞开”,而他自己所在的棋盘是大小为 N*M 的长方形,他可以向上下左右四个方向移动(不可走有障碍点)。棋盘中有一扇门。根据机关的提示,小明顿时明白了,他和朋友必须在第 t 秒到门口。而这一切,没有回头路!因为一旦他移动了,他刚才所在的点就会消失,并且他不能在一个点上停留超过一秒,不然格子会爆炸。大逃亡开始了,请问小明和朋友能安全的逃出这奇怪的棋盘吗?
Input
输入多组测试数据。每个测试用例的第一行包含三个整数 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分别表示棋盘的大小和门打开的时间。接下来的N行给出棋盘布局,每一行包含M个字符。其中
“.”: 无障碍点
“X”: 障碍点
“S”: 起点
“D”: 门
输入以 3 个 0 结束。这个测试用例不需要处理。
Output
对于每组样例输出一行。
如果小明能够安全逃出,输出 “YES” ,否则输出 “NO”。
Sample Input
4 4 5
S.X.
…X.
…XD
…
3 4 5
S.X.
…X.
…D
0 0 0
Sample Output
NO
YES
注意:
这题有许多坑,至少我wa了好多次;
1.棋盘输入必须有%s(用%c wa了);
2.必须奇偶剪枝,否则后超时;
3.必须统计障碍点数,有n*m-jw-1>=lim;(其中n是纵数,m是行数,jw是障碍点数,lim是门打开的时间数)可以快速在障碍点过多的情况下,避免深搜,得出结果;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char arr[10][10];
int open[10][10];
int n,m,lim,flag=0,ex=0,ey=0;
int np[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void DFS(int x,int y ,int step){
if(x==ex&&y==ey&&step==lim){
flag=1;
return ;
}
//在已可逃离情况下,将所有深搜停止,减少运行时间;
if(step>=lim||flag==1)
return ;
//奇偶剪枝
int s=(lim-step)-abs(x-ex)-abs(y-ey);
if(s<0||s%2==1)
return ;
for(int i=0;i<4;i++){
int nx=x+np[i][0];
int ny=y+np[i][1];
if(nx<0||ny<0||nx>=n||ny>=m||open[nx][ny]==1||arr[nx][ny]=='X')
continue;
open[nx][ny]=1;
DFS(nx,ny,step+1);
open[nx][ny]=0;
}
}
int main()
{
int bx=0,by=0,jw=0;
while(scanf("%d %d %d",&n,&m,&lim)!=EOF&&n!=0&&m!=0&&lim!=0){
memset(open,0,sizeof(open));
flag=0,jw=0;
for(int i=0;i<n;i++)
scanf("%s",arr[i]);
for(int i=0;i<n;i++){
for(int t=0;t<m;t++){
if(arr[i][t]=='S')
bx=i,by=t;
else if(arr[i][t]=='D')
ex=i,ey=t;
else if(arr[i][t]=='X')
jw++;
}
}
int s=abs(ex-bx)+abs(ey-by);
if(s<=lim&&(lim-s)%2==0&&n*m-jw-1>=lim){//奇偶剪枝加障碍排除(!!!)
open[bx][by]=1;
DFS(bx,by,0);
}
if(flag==0)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}