思路:BFS。用v[x][y][sx][sy]来标记箱子在(x,y),人在(sx,sy)时的状态。用way[x][y][sx][sy]来保存路径。
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; struct six { int push,walk; int v; }v[22][22][22][22]; struct data { char dir; int fbx,fby,fsx,fsy; }way[22][22][22][22]; struct lenka { int bx,by,sx,sy; }; int n,m; char s[21][21]; int d[4][2]={-1,0,0,-1,1,0,0,1}; void bfs(int bx,int by,int sx,int sy) { memset(v,0,sizeof v); v[bx][by][sx][sy].v=1; v[bx][by][sx][sy].push=0; v[bx][by][sx][sy].walk=0; way[bx][by][sx][sy].dir=0; queue<struct lenka>p; p.push((lenka){bx,by,sx,sy}); while(!p.empty()) { lenka now=p.front();p.pop(); for(int i=0;i<4;i++) { int nx=now.sx+d[i][0]; int ny=now.sy+d[i][1]; if(nx>=0&&nx<n&&ny>=0&&ny<m&&s[nx][ny]=='.') { if(nx==now.bx&&ny==now.by) //人走到箱子的位置了 { int bx=now.bx+d[i][0]; int by=now.by+d[i][1]; if(bx>=0&&bx<n&&by>=0&&by<m&&s[bx][by]=='.') //人能把箱子向当前方向推走 { if(v[bx][by][nx][ny].v==0||(v[bx][by][nx][ny].push>v[now.bx][now.by][now.sx][now.sy].push+1)||((v[bx][by][nx][ny].push==v[now.bx][now.by][now.sx][now.sy].push+1)&&(v[bx][by][nx][ny].walk>v[now.bx][now.by][now.sx][now.sy].walk))) { v[bx][by][nx][ny].push=v[now.bx][now.by][now.sx][now.sy].push+1; v[bx][by][nx][ny].walk=v[now.bx][now.by][now.sx][now.sy].walk; v[bx][by][nx][ny].v=1; if(i==0)way[bx][by][nx][ny].dir='N'; if(i==1)way[bx][by][nx][ny].dir='W'; if(i==2)way[bx][by][nx][ny].dir='S'; if(i==3)way[bx][by][nx][ny].dir='E'; way[bx][by][nx][ny].fbx=now.bx; way[bx][by][nx][ny].fby=now.by; way[bx][by][nx][ny].fsx=now.sx; way[bx][by][nx][ny].fsy=now.sy; p.push((lenka){bx,by,nx,ny}); } } } else //人所在的位置推不了箱子 { if(v[now.bx][now.by][nx][ny].v==0||(v[now.bx][now.by][nx][ny].push>v[now.bx][now.by][now.sx][now.sy].push)||((v[now.bx][now.by][nx][ny].push==v[now.bx][now.by][now.sx][now.sy].push&&v[now.bx][now.by][nx][ny].walk>v[now.bx][now.by][now.sx][now.sy].walk+1))) { v[now.bx][now.by][nx][ny].push=v[now.bx][now.by][now.sx][now.sy].push; v[now.bx][now.by][nx][ny].walk=v[now.bx][now.by][now.sx][now.sy].walk+1; v[now.bx][now.by][nx][ny].v=1; if(i==0)way[now.bx][now.by][nx][ny].dir='n'; if(i==1)way[now.bx][now.by][nx][ny].dir='w'; if(i==2)way[now.bx][now.by][nx][ny].dir='s'; if(i==3)way[now.bx][now.by][nx][ny].dir='e'; way[now.bx][now.by][nx][ny].fbx=now.bx; way[now.bx][now.by][nx][ny].fby=now.by; way[now.bx][now.by][nx][ny].fsx=now.sx; way[now.bx][now.by][nx][ny].fsy=now.sy; p.push((lenka){now.bx,now.by,nx,ny}); } } } } } } void dfs(int bx,int by,int nx,int ny) { if(way[bx][by][nx][ny].dir==0)return; dfs(way[bx][by][nx][ny].fbx,way[bx][by][nx][ny].fby,way[bx][by][nx][ny].fsx,way[bx][by][nx][ny].fsy); printf("%c",way[bx][by][nx][ny].dir); } int main() { int cas=1; while(scanf("%d%d",&n,&m)!=EOF&&(n||m)) { int sx,sy,bx,by,tx,ty; memset(way,0,sizeof way); for(int i=0;i<n;i++)scanf("%s",s[i]); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(s[i][j]=='S')sx=i,sy=j,s[i][j]='.'; if(s[i][j]=='B')bx=i,by=j,s[i][j]='.'; if(s[i][j]=='T')tx=i,ty=j,s[i][j]='.'; } } bfs(bx,by,sx,sy); printf("Maze #%d\n",cas++); int flag=0,push=10000,walk=10000; for(int i=0;i<4;i++) { int x=tx+d[i][0]; int y=ty+d[i][1]; if(x>=0&&x<n&&y>=0&&y<m&&s[x][y]=='.')//找符合条件的路径 { if(v[tx][ty][x][y].v&&(v[tx][ty][x][y].push<push||(v[tx][ty][x][y].push==push&&v[tx][ty][x][y].walk<walk))) { bx=tx,by=ty,sx=x,sy=y; push=v[tx][ty][x][y].push; walk=v[tx][ty][x][y].walk; flag=1; } } } if(flag==0)puts("Impossible."); else{dfs(bx,by,sx,sy);printf("\n");} printf("\n"); } return 0; }