poj 2049 Finding Nemo(bfs+优先队列)
题意:
Marlin去找困在迷宫中的Nemo,墙壁不可以穿过,但是墙上的门可以穿过,问Marlin最少穿过几扇门可以找到Nemo,无法到达输出-1.
分析:
这题比较麻烦的地方是怎么判断格子的一条边是墙壁还是门还是什么都没有。为了区别是哪条边,我用一个80000的g数组去判断,给每条边一个ID值去区分。与x轴平行的边是x+y*200,与y轴平行的边是40000+200*x+y,其中x和y是每个格子的lower-left point(上图看是左下角的点)。这样就可以区分每一条边。有门设为2,有墙设为1,什么都没有为0。接下来就是bfs了,因为有可能从一个格子到另一个格子不需要串过门,所以用队列的话可能并不能得到最优解。采用优先队列,每次取出的位置一定是当前经过门最少的,这样就很好做了。具体参考代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<stack> #include<map> #include<vector> #include<queue> using namespace std; #define mp make_pair typedef long long ll; const int INF=0x3f3f3f3f; const int N=222; typedef pair<double,double>pdd; typedef pair<int,pdd>pi; int g[80000+9]; int maxx,minx,maxy,miny; bool vis[N][N]; int bfs(double x,double y) { priority_queue<pi,vector<pi>,greater<pi> >q; q.push(mp(0,mp(x,y))); while(!q.empty()){ pi t=q.top();q.pop(); int step=t.first; x=t.second.first; y=t.second.second; if(x>maxx||x<minx||y>maxy||y<miny){return step;} int x1=(int)x;int x2=x1+1; int y1=(int)y;int y2=y1+1; if(vis[x1][y1])continue; vis[x1][y1]=1; if(g[x1+200*y1]==2)q.push(mp(step+1,mp(x,y-1))); else if(!(g[x1+200*y1]==1))q.push(mp(step,mp(x,y-1))); if(g[40000+x1*200+y1]==2)q.push(mp(step+1,mp(x-1,y))); else if(!(g[40000+x1*200+y1]==1))q.push(mp(step,mp(x-1,y))); if(g[x1+200*y2]==2)q.push(mp(step+1,mp(x,y+1))); else if(!(g[x1+200*y2]==1))q.push(mp(step,mp(x,y+1))); if(g[40000+x2*200+y1]==2)q.push(mp(step+1,mp(x+1,y))); else if(!(g[40000+x2*200+y1]==1))q.push(mp(step,mp(x+1,y))); } return -1; } int main() { int n,m; while(~scanf("%d%d",&n,&m)&&(n!=-1||m!=-1)){ memset(vis,0,sizeof(vis)); memset(g,0,sizeof(g)); minx=miny=INF; maxx=maxy=-INF; int nn=n; int x,y,t,l; while(n--){ scanf("%d%d%d%d",&x,&y,&t,&l); minx=min(minx,x);maxx=max(maxx,x); miny=min(miny,y);maxy=max(maxy,y); if(t==0){ for(int i=x;i<x+l;i++){ g[y*200+i]=1; } } else for(int i=y;i<y+l;i++)g[40000+x*200+i]=1; } while(m--){ scanf("%d%d%d",&x,&y,&t); if(t==0)g[y*200+x]=2; else g[40000+x*200+y]=2; } double xx,yy; scanf("%lf%lf",&xx,&yy); if(nn<4){printf("0\n");continue;} printf("%d\n",bfs(xx,yy)); } return 0; }