HDU 1010

题目链接:HDU 1010
n*m的迷宫,'X’代表墙,'S’起点,‘D’出口,’.'代表路,问能不能在 t 秒走出。
Sample Input

 4 4 5
 S.X.
 ..X.
 ..XD
 ....
 3 4 5
 S.X.
 ..X.
 ...D
 0 0 0

Sample Output

NO
YES

注意题目要求是正好在 t 秒是否能走出,不能用BFS,因为bfs找到的最短路不一定是需要的 t 秒,且bfs是在邻点逐步扩张,可能会把需要的点占去。用DFS+回溯,但是需要考虑剪枝,即一旦判断某一步时再往下走的话无论如何都不会到达终点或者满足题意,直接跳出判断,输出结果。
奇偶剪枝
1,奇偶剪枝
设起点(x1,y1),终点(x2,y2),那么从起点到终点的最短路劲为abs(x1-x2)+abs(y1-y2)。
在这里插入图片描述
从起点到终点走的任意非最短路径所走的步数减去最短路径的步数一定为偶数
在这里插入图片描述
若为奇数,则一定不能到达。
2,路径剪枝
当走的路用去的时间等于 t 时且还没有走到终点,结束。
当全图能走的路花费时间小于 t 时,结束。

代码:

#include <iostream>
#include <cmath>
#include <cstring>
const int maxn = 10;
using namespace std;
char map[maxn][maxn];
int dis[][2]= {1,0,-1,0,0,1,0,-1};
int n,m,t,beg,endd,flag;
void dfs(int xx,int yy,int ans)
{
	if(xx==beg&&yy==endd&&ans==t)
	{
		flag=1;
		return ;
	}
	int p=t-ans-(abs(xx-beg)+abs(yy-endd));//当前剩余步数(t-ans)减去最短路径所需步数(abs(xx-beg)+abs(yy-endd))
	if(p<0||p&1)//判断奇偶或是否能走出
		return;
	for(int i=0; i<4; i++)
	{
		int dx=xx+dis[i][0];
		int dy=yy+dis[i][1];
		if(dx>=0&&dx<n&&dy>=0&&dy<m&&map[dx][dy]!='X')
		{
			map[dx][dy]='X';//将走过的路变为墙
			dfs(dx,dy,ans+1);
			map[dx][dy]='.';//回溯,将该点重置为路
		}
	}
	return;
}
int main()
{
	int x,y,obs;
	while(cin>>n>>m>>t&&n&&m&&t)
	{
		flag=0,obs=0;
		for(int i=0; i<n; i++)
			for(int j=0; j<m; j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='S')
					x=i,y=j;
				if(map[i][j]=='D')
					beg=i,endd=j;
				if(map[i][j]=='X')
					obs++;
			}
		if(n*m-obs<=t)//当全图能走的路花费时间小于 t 时,结束
		{
			cout<<"NO"<<endl;
			continue;
		}
		map[x][y]='X';
		dfs(x,y,0);
		if(flag)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值