题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
给出中文翻译:
暑假的时候,小明和朋友去迷宫中寻宝。然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱!他们想尽一切办法逃出去。
迷宫是一个大小为 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
思路:注意剪枝和回溯!代码:
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
char map[10][10];
int vis[10][10];
int n,m,T,x0,y0,a,b;
bool flag;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
void DFS(int x,int y,int t)
{
vis[x][y]=1;
if(map[x][y]=='D'&&t==T)
{
flag=1;
return ;
}
if(((T-t)%2 != (abs(x-x0) + abs(y-y0)) %2)) return; //判断和剪枝
//int ans=T-t-(abs(x-x0)+abs(y-y0)); //该步操作称为奇偶剪枝
//if(ans<0||ans%2==1) return ;
for(int i=0;i<4;i++)
{
int x2=x+dir[i][0];
int y2=y+dir[i][1];
if(x2>=0&&x2<n&&y2>=0&&y2<m&&!vis[x2][y2]&&map[x2][y2]!='X')
{
DFS(x2,y2,t+1);
if(flag) return ;
vis[x2][y2]=0; //回溯
}
}
}
int main()
{
while(cin>>n>>m>>T&&n&&m&&T)
{
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
flag=false;
for(int i=0;i<n;i++)
cin>>map[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(map[i][j]=='D') //记录终点坐标
{
x0=i;
y0=j;
}
if(map[i][j]=='S') //记录起点坐标
{
a=i;
b=j;
}
}
}
DFS(a,b,0);
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
ps:勇士之魂,从未破灭!