poj2049 Finding Nemo(优先队列BFS)

(1)这题细节比较多,nemo的位置可能会很大(例如(100000,1000000));

(2)一开始优先队列用错了,习惯性的写成了先出经过门最多的点,一直wa。。

(3)意外发现了一组神数据,如果bfs时标记了的话,这组数据可能不对,卡位卡的好啊,总结就是使用优先队列bfs应该在出队的时候标记,而不是在进队的时候标记;

这组数据就是 :

4 1
3 2 1 1
1 3 0 2
1 1 0 2
1 1 1 2
2 1 1
1.5 1.5

答案应该是0
可以画画


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <map>
#include <string>
#include <cmath>
#define maxn 300
#define LL long long
using namespace std;

struct ttt
{
	int edge[4];//s x z y 0NULL  1WALL,2DOOR
}_map[maxn][maxn];
bool vis[maxn][maxn];
int mx[]={0,0,-1,1};
int my[]={1,-1,0,0};
struct node
{
	int x,y;
	int step;
//	vector<int>que;
	friend bool operator<(node a,node b)
	{
		return a.step<b.step;
	}
	friend bool operator>(node a,node b)
	{
		return a.step>b.step;
	}
};

int main()
{
	int m,n;
	while( scanf("%d%d",&m,&n),n>=0 || m>=0)
	{
		memset(_map,0,sizeof(_map));
		for(int i=0;i<m;++i)
		{
			int x,y,d,t;
			scanf("%d%d%d%d" ,&x,&y,&d,&t);
			for(int j=0;j<t;++j)
			{
				if(d==0)
				{
					_map[x+j][y].edge[1]=1;
					if(y>0)
						_map[x+j][y-1].edge[0]=1;
				}
				else
				{
					_map[x][y+j].edge[2]=1;
					if(x>0)
						_map[x-1][y+j].edge[3]=1;
				}
			}
		}
		for(int i=0;i<n;++i)
		{
			int x,y,d;
			scanf("%d%d%d",&x,&y,&d);
			if(d==0)
			{
				_map[x][y].edge[1]=2;
				if(y>0)
					_map[x][y-1].edge[0]=2;
			}
			else
			{
				_map[x][y].edge[2]=2;
				if(x>0)
					_map[x-1][y].edge[3]=2;
			}
		}
		double x,y;
		scanf("%lf%lf",&x,&y);
		int sx,sy;
		sx=floor(x);
		sy=floor(y);
		if(sx<0 || sy<0 || sx>199 || sy>199 )
		{
			printf("0\n");
			continue;
		}
		node now;
//		now.que.clear();
		now.x=sx;
		now.y=sy;
		now.step=0;
		priority_queue<node,vector<node>,greater<node> >que;
		memset(vis,false,sizeof(vis));
		vis[sx][sy]=true;
		que.push(now);
		bool flag=false;
		node ans;
		while(!que.empty())
		{
			node temp=que.top();
			que.pop();
			vis[temp.x][temp.y]=true;//在这标记
			if(temp.x>=200 || temp.y>=200 ||temp.x<=0 || temp.y<=0)
			{
				ans=temp;
				flag=true;
				break;
			}
			for(int i=0;i<4;++i)
			{
				int nx=temp.x+mx[i];
				int ny=temp.y+my[i];
				now=temp;
				if(nx>=0 && ny>=0 && ny<201 && nx<201 && !vis[nx][ny]
																  &&  _map[temp.x][temp.y].edge[i]!=1)
				{
//					cout<<nx<<"  "<<ny<<endl;
//					vis[nx][ny]=true; //不能在这标记,但是这题数据水,在这标记也能过
					now.step=temp.step;
					if(_map[temp.x][temp.y].edge[i]==2)
					{
						now.step+=1;
					}
					now.x=nx;
					now.y=ny;
//					now.que.push_back(nx*10+ny);
					que.push(now);
				}
			}
		}
//		for(int i=0;i<ans.que.size();++i)
//		{
//			cout<<ans.que.at(i)<<endl;
//		}
		if(flag)
			printf("%d\n",ans.step);
		else
			printf("-1\n");
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值