题目链接:http://poj.org/problem?id=1475
题目大意及思路:我用的普通的优先队列bfs效率比较低,主要是有很多冗余状态,据说可以双重bfs,因为推的次数最少是主要目标,所以可以作为外层bfs,walk则作为内层bfs.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
int dp[22][22][22][22];
int rec[22][22][22][22];
int vst[22][22][22][22];
char mp[22][22];
int dx[4][2]={0,1,0,-1,1,0,-1,0};
int path[1000];
char dic[9]={"EWSNewsn"};
int sx,sy,ex,ey,bx,by,n,m,ans;
int tx,ty,txx,tyy;
struct node
{
int x,y,xx,yy,dp;
bool operator<(const node a)const
{
return dp>a.dp;
}
}rec2[22][22][22][22];
void bfs()
{
priority_queue<node>q;
int x,y,xx,yy,i,j;
node st,ct;
st.x=bx;st.y=by;
st.xx=sx;st.yy=sy;
st.dp=0;
q.push(st);
vst[bx][by][sx][sy]=1;
while(!q.empty())
{
st=q.top();
q.pop();
// printf("st x %d y %d xx %d yy %d dp %d\n",st.x,st.y,st.xx,st.yy,st.dp);
for(i=0;i<4;i++)
{
xx=st.xx+dx[i][0];
yy=st.yy+dx[i][1];
if(xx>=0&&yy>=0&&xx<n&&yy<m&&mp[xx][yy]!='#')
{
ct=st;
ct.xx=xx;ct.yy=yy;
if(xx==st.x&&yy==st.y)
{
x=2*xx-st.xx;
y=2*yy-st.yy;
if(x>=0&&y>=0&&x<n&&y<m&&mp[x][y]!='#')
{
ct.x=x;ct.y=y;
if(vst[ct.x][ct.y][ct.xx][ct.yy])
continue;
vst[ct.x][ct.y][ct.xx][ct.yy]=1;
rec[ct.x][ct.y][ct.xx][ct.yy]=i;
rec2[ct.x][ct.y][ct.xx][ct.yy]=st;
ct.dp=st.dp+4000;
// printf("x %d y %d xx %d yy %d dp %d\n",ct.x,ct.y,ct.xx,ct.y,ct.dp);
if(x==ex&&y==ey)
{
//ans=dp[ct.x][ct.y][ct.xx][ct.yy];
ans=ct.dp;
tx=x;ty=y;txx=xx;tyy=yy;
return;
}
q.push(ct);
}
}
else
{
if(vst[ct.x][ct.y][ct.xx][ct.yy])
continue;
// printf("yyyy");
vst[ct.x][ct.y][ct.xx][ct.yy]=1;
rec[ct.x][ct.y][ct.xx][ct.yy]=i+4;
rec2[ct.x][ct.y][ct.xx][ct.yy]=st;
ct.dp=st.dp+1;
q.push(ct);
// printf("x %d y %d xx %d yy %d dp %d\n",ct.x,ct.y,ct.xx,ct.yy,ct.dp);
}
}
}
}
ans=inf;
}
int main()
{
int i,j,count=1;
while(scanf("%d%d",&n,&m),n|m)
{
memset(vst,0,sizeof(vst));
for(i=0;i<n;i++)
scanf("%s",mp[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(mp[i][j]=='S')
sx=i;sy=j;
if(mp[i][j]=='T')
ex=i;ey=j;
if(mp[i][j]=='B')
bx=i;by=j;
}
bfs();
printf("Maze #%d\n",count++);
if(ans==inf)
{
printf("Impossible.\n");
puts("");
continue;
}
int tmpx,tmpy,tmpxx,tmpyy;
int cnt=0;
while(tx!=bx||ty!=by||txx!=sx||tyy!=sy)
{
tmpx=tx;tmpy=ty;tmpxx=txx;tmpyy=tyy;
path[cnt++]=rec[tx][ty][txx][tyy];
tx=rec2[tmpx][tmpy][tmpxx][tmpyy].x;
ty=rec2[tmpx][tmpy][tmpxx][tmpyy].y;
txx=rec2[tmpx][tmpy][tmpxx][tmpyy].xx;
tyy=rec2[tmpx][tmpy][tmpxx][tmpyy].yy;
}
for(i=cnt-1;i>=0;i--)
{
printf("%c",dic[path[i]]);
}
puts("");
puts("");
}
}