暑假的时候,小明和朋友去迷宫中寻宝。然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱!他们想尽一切办法逃出去。
迷宫是一个大小为 N*M 的长方形,迷宫中有一扇门。一开始,门是关着的,他会在第 t 秒的时间打开。因为,小明和朋友必须在第 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
题意不用多说,主要是理解减枝的思想,当遇到不满足条件的递归分枝时就返回,即减枝。
首先判断可走的点的数目是否大于要求的时间,如果小于等于就输出NO。
1.如果当前步数(step) >= T 而且还没有找到D点,则返回。
2.设当前位置(x, y)到D点(dx, dy)的最短距离为s,到达当前位置(x, y)已经花费时间(步数)step,那么,如果题目要求的时间T - step < s,则剪掉。
3. 对于当前位置(x, y),如果,(T-step-s)是奇数,则剪掉(奇偶剪枝)。
减枝部分内容来自 https://blog.csdn.net/chyshnu/article/details/6171758
代码如下
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
int vis[15][15];
char map[15][15];
int n,m,t,flag=0,sx,sy,ex,ey;
int ad[4][2]={1,0,0,1,-1,0,0,-1};
void dfs(int x,int y,int step){
if(flag) return;
if(map[x][y]=='D' && step==t){
flag=1;
return;
}
if(step>=t) return;
int s=abs(x-ex)+abs(y-ey);
if(t-step<s) return;
int dis=t-step-s;
if(dis<0 || dis%2!=0) return;
int dxx,dyy;
for(int i=0;i<4;i++){
dxx=x+ad[i][0];
dyy=y+ad[i][1];
if(dxx>=0 && dxx<n && dyy>=0 && dyy<m && map[dxx][dyy]!='X'&& vis[dxx][dyy]==0){
vis[dxx][dyy]=1;
dfs(dxx,dyy,step+1);
vis[dxx][dyy]=0;
}
}
}
int main() {
int xnumber=0;
while(cin>>n>>m>>t,n+m+t){
memset(vis,0, sizeof(vis));
memset(map,0, sizeof(map));
xnumber=0;
getchar();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%c",&map[i][j]);
}
getchar();
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(map[i][j]=='S'){
sx=i;
sy=j;
vis[i][j]=1;
}else if(map[i][j]=='D')
{
ex=i;
ey=j;
}else if(map[i][j]=='X')
{
xnumber++;
}
}
}
flag=0;
if(n*m-xnumber>t){
dfs(sx,sy,0);
}
if(flag){
cout<<"YES"<<endl;
} else cout<<"NO"<<endl;
}
return 0;
}