HDU 1010 Tempter of the Bone 【DFS+剪枝+回溯】

题目链接: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:勇士之魂,从未破灭!

猜你喜欢

转载自blog.csdn.net/LOOKQAQ/article/details/81384124
今日推荐