UVA 1600 - Patrol Robot

这题是一道简单的BFS,原本没有AC是以为不能走重复的路。后来发现这不是一道普通的BFS,也就是说,我可以往回走(走已经走过的结点),找到更优的解决方案.所以我们要设置一个记录障碍信息的数组(且称为bar),这个数组记录了当前节点已经走过的障碍数.(0,1,2,...,k)。

1.如果已经连续穿越了K的障碍,下一个他只能走到不是障碍(maze[x][y]==0)的地方。

2.如果BFS过程中,发现当前节点走到已经走过的节点的所需要穿越的障碍数量更少,覆盖掉已经走过的哪一个结点。

其余部分和普通BFS没有区别。

 

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int dis[25][25];	//记录距离 
int maze[25][25];	//迷宫情况 
int bar[25][25];	//记录点 x,y 的已走过的障碍数量 
int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int n,m,k;
queue <pair<int,int> > q;	//队列,记录x,y; 
pair<int,int> p;
bool BFS(int x,int y)
{
	for (int i=0;i<4;i++)
	{
		// 对x,y 四周探测,对符合条件的节点进行更新 (注意后两个条件) 
		if (x+dx[i]>=1&&x+dx[i]<=m&&y+dy[i]>=1&&y+dy[i]<=n&&(bar[x][y]+1<bar[x+dx[i]][y+dy[i]]||dis[x+dx[i]][y+dy[i]]==-1))
		{
		
			if (maze[x+dx[i]][y+dy[i]]==1&&bar[x][y]<k) 
			{
				bar[x+dx[i]][y+dy[i]]=bar[x][y]+1;
				dis[x+dx[i]][y+dy[i]]=dis[x][y]+1;
				p.first=x+dx[i];
				p.second=y+dy[i];
				q.push(p);
			}
			else if (maze[x+dx[i]][y+dy[i]]==0)
			{
				bar[x+dx[i]][y+dy[i]]=0;
				dis[x+dx[i]][y+dy[i]]=dis[x][y]+1;
				p.first=x+dx[i];
				p.second=y+dy[i];
				q.push(p);
			}
			if (x+dx[i]==m&&y+dy[i]==n)
				return true;//找到终点后,返回真,BFS可以结束 
		}
	}
	return false;
}
int main()
{
	int t,x,y;
	scanf ("%d",&t);
	while(t--)
	{
		scanf ("%d %d",&m,&n);
		scanf ("%d",&k);
		memset(dis,-1,sizeof(dis));
		memset(bar,-1,sizeof(bar));
		memset(maze,-1,sizeof(maze));
		for (int i=1;i<=m;i++)
		{
			for (int j=1;j<=n;j++)
			{
				scanf ("%d",&maze[i][j]);
			}
		}
		p.first=1;
		p.second=1;
		dis[1][1]=0;
		bar[1][1]=0;
		q.push(p);
		while(!q.empty())
		{
			x=q.front().first;
			y=q.front().second;
			if (BFS(x,y))
				break;
			q.pop();
		}
		while(!q.empty())
			q.pop();
		printf ("%d\n",dis[m][n]);
	}
	return 0;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值