hdu 1254 推箱子 雙層bfs
阿新 • • 發佈:2019-02-17
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <iostream> #include <algorithm> using namespace std; #define LL __int64 const int INF=1e8; const int maxn=10; int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}}; int n,m; struct node{ int x,y; }; struct node2{ int x,y,xx,yy,step;//x,y是人所在位置,xx,yy為箱子所在位置 }; int e[maxn][maxn],vis[maxn][maxn],x3,y3,mark[maxn][maxn][5]; int bfs(int x1,int y1,int x2,int y2,int x,int y)//判斷人能否到達箱子前進方向的後方,即能否推箱子 { queue<node>qq; node ff,gg; int i,j,k,xx,yy; memset(vis,0,sizeof(vis)); ff.x=x1;ff.y=y1; vis[x1][y1]=1; qq.push(ff); while(!qq.empty()) { ff=qq.front(); qq.pop(); if(ff.x==x2&&ff.y==y2) { while(!qq.empty()) qq.pop(); return 1; } for(i=0;i<4;i++) { xx=ff.x+dir[i][0]; yy=ff.y+dir[i][1]; if(xx==x&&yy==y)continue;//箱子也是不能穿過的 if(xx<0||yy<0||xx>=n||yy>=m||e[xx][yy]==1||vis[xx][yy]==1)continue; gg.x=xx;gg.y=yy; vis[xx][yy]=1; qq.push(gg); } } return 0; } void bfs2(int x1,int y1,int x2,int y2)//推箱子 { queue<node2>q; node2 f,g; int i,j,xx,yy,xxx,yyy; f.x=x1;f.y=y1;f.xx=x2;f.yy=y2;f.step=0; q.push(f); while(!q.empty()) { f=q.front(); q.pop(); if(f.xx==x3&&f.yy==y3){printf("%d\n",f.step);while(!q.empty())q.pop();return;} for(i=0;i<4;i++) { xx=f.xx+dir[i][0]; yy=f.yy+dir[i][1]; xxx=f.xx-dir[i][0]; yyy=f.yy-dir[i][1]; if(xx<0||yy<0||xx>=n||yy>=m||xxx<0||yyy<0||xxx>=n||yyy>=m)continue; if(e[xx][yy]==1||e[xxx][yyy]==1||mark[xx][yy][i])continue; if(!bfs(f.x,f.y,xxx,yyy,f.xx,f.yy))continue; g.x=f.xx;g.y=f.yy; g.xx=xx;g.yy=yy;g.step=f.step+1; mark[xx][yy][i]=1; q.push(g); } } printf("-1\n"); } int main() { int T; scanf("%d",&T); while(T--) { int i,j,k,x1,y1,x2,y2; x3=y3=-1; scanf("%d%d",&n,&m); for(i=0;i<n;i++) for(j=0;j<m;j++) { scanf("%d",&e[i][j]); if(e[i][j]==3){x3=i;y3=j;} if(e[i][j]==4){x1=i;y1=j;} if(e[i][j]==2){x2=i;y2=j;} } memset(mark,0,sizeof(mark)); bfs2(x1,y1,x2,y2); } return 0; } /* 推箱子,每次箱子進一個都要更新人的位置,還要判斷人是否能到箱子前進方向的後方,不然不能推。兩個bfs解決。 這裡的難點就是箱子可能往回走,詳細見特例。所以直接標記位置是不可以的,還要標記推過了的方向,所以要三維陣列標記。(我在這背坑個半死。。) 特例: 4 3 0 0 0 0 0 1 0 2 3 1 4 1 6 3 0 0 0 0 0 0 1 0 0 0 0 1 0 2 3 1 4 1 */