题意:
给一个由墙和门组成的迷宫,求从原点到目标点最少要经过多少道门。
分析:
有人用bfs来,结果写的是介于bfs和最短路中间不伦不类的算法。。这题边权为0或1,用bfs求最短路靠谱么??bfs是只能求边权恒定的最短路,这题用bfs过的是因为把bfs写成了spfa(spfa本来就是一种优化的bfs算法),bfs是什么?搜索,搜索的含义是搜到一个状态以后就不会再经过这个状态了,故在bfs里对任何状态只有把vis[s]置为1的过程,没有把vis[s]置0的过程。spfa的区别是同时有把vis[s]置0和置1的过程(所以可处理不定长边)。个人认为解题还是思路清晰一些好,不要过了就不管了。
另外这题的spfa比较特殊,没有置1的过程,这样会加入冗余节点,但保证了每个节点和到该节点方向的一致性。
代码:
//poj 2049
//sep9
#include <iostream>
#include <queue>
using namespace std;
const int maxN=205;
int dis[maxN][maxN],inq[maxN][maxN];
int g[maxN][maxN][4];
int wn,dn,startXI,startYI;
double startXF,startYF;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
struct node{
int x,y,dir;
};
queue<node> q;
int changeDir(int old)
{
if(old==0) return 1;
if(old==1) return 0;
if(old==2) return 3;
if(old==3) return 2;
}
void spfa()
{
while(!q.empty()) q.pop();
memset(inq,0,sizeof(inq));
node cur;
cur.x=startXI,cur.y=startYI,cur.dir=-1;
dis[startXI][startYI]=0;
q.push(cur);
inq[startXI][startYI]=1;
while(!q.empty()){
cur=q.front();q.pop();
int x=cur.x,y=cur.y,steps=dis[x][y];
inq[x][y]=0;
if(x==0&&y==1) continue;
for(int d=0;d<4;++d){
if(d==cur.dir) continue;
if(g[x][y][d]==1) continue;
int newx=x+dir[d][0];
int newy=y+dir[d][1];
if(newx<0||newx>202||newy<0||newy>202) continue;
int newdir=changeDir(d);
int newsteps;
if(g[x][y][d]==2) newsteps=steps+1;
else newsteps=steps;
if(newsteps>dis[0][1]) continue;
if(newsteps<dis[newx][newy]){
dis[newx][newy]=newsteps;
if(!inq[newx][newy]){
node ncur;
ncur.x=newx,ncur.y=newy,ncur.dir=newdir;
q.push(ncur);
}
}
}
}
}
int main()
{
while(scanf("%d%d",&wn,&dn)==2){
if(wn==-1&&dn==-1)
break;
for(int i=0;i<maxN;++i)
for(int j=0;j<maxN;++j)
dis[i][j]=INT_MAX;
memset(g,0,sizeof(g));
int x,y,d,t;
while(wn--){
cin>>x>>y>>d>>t;
if(d==1)
for(int j=y+1;j<=y+t;++j)
g[x][j][2]=g[x-1][j][3]=1;
else
for(int j=x;j<x+t;++j)
g[j][y][0]=g[j][y+1][1]=1;
}
while(dn--){
cin>>x>>y>>d;
if(d==1)
g[x][y+1][2]=g[x-1][y+1][3]=2;
else
g[x][y+1][1]=g[x][y][0]=2;
}
cin>>startXF>>startYF;
startXI=(int)startXF;
startYI=(int)startYF+1;
if(startXI<0||startXI>199||startYI<0||startYI>199)
cout<<0<<endl;
else{
spfa();
if(dis[0][1]==INT_MAX) cout<<-1<<endl;
else cout<<dis[0][1]<<endl;
}
}
return 0;
}