hdu 1728 逃离迷宫

21 篇文章 0 订阅

以为这题和连连看一样水,就很开心的用了dfs然后tle了无数次,好吧,我bfs总行了吧,然后wa了无数次.................

之所以wa是因为在bfs的过程中有些点是可以重复加入队列的.

例如

1
3 3
..*
...
*.*
1 1 1 2 3

这组数据(行,列)

1 (1,1)→(1,2)→(2,2)→(2,3)要转2次弯;

2 (1,1)→(2,1)→(2,2)→(2,3)只转1次弯;所以应该输出yes;

从上面的数据可以看出2次搜索都搜索到了(2,2)这个点,但是2次搜索到改点时的状态却不一样,1中经过该点时转了2次弯,而2种经过该点时却是转了1次弯,因此虽然(2,2)已走过,由于2中的状态要优于1中的状态(转弯次数较小),我们再次搜索到该点时,任要将他加入队列,这和hdu 4528很像.所以我们不能只单纯的标记每个点有没有走过,而是要标记走过该点的状态如何.如果上面的数据能过,那就基本上没问题了.下面为ac代码

#include<iostream>
#include<queue>
#include<cstring>
#define maxn 100+5
using namespace std;
int n,m;
int k,x1,y1,x2,y2;
char mapp[maxn][maxn];
int visit[maxn][maxn];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int flag;
struct stu
{
	int x,y,di,lim;
};
void bfs()
{
	stu x,y;
	queue<stu>root;
	x.x=x1;x.y=y1;x.di=-1;x.lim=-1;
	root.push(x);
	visit[x.x][x.y]=0;
	while(root.size())
	{
		x=root.front() ;
		root.pop();
		if(x.x==x2&&x.y==y2){flag=1;return;}
		for(int i=0;i<4;i++)
		{
			y.x=x.x+dir[i][0];
			y.y=x.y+dir[i][1];
			y.di=x.di;
			y.lim=x.lim;
			if(y.di!=i) y.di=i,y.lim++;
			if(y.x<0||y.x>=n||y.y<0||y.y>=m||visit[y.x][y.y]<y.lim||mapp[y.x][y.y]=='*'||y.lim>k) {continue;}
			root.push(y);
			//cout<<y.x<<y.y<<endl;
			visit[y.x][y.y]=y.lim; 
		}
	}
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=0;i<n;i++) cin>>mapp[i];
		cin>>k>>y1>>x1>>y2>>x2;
		y1--;x1--;y2--;x2--;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				visit[i][j]=1<<20;
			} 
		}
		flag=0;
		bfs();
		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、付费专栏及课程。

余额充值