hdu_1254_推箱子(双BFS)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1254
题解:以箱子为主体,第一层BFS,然后用第二层BFS来判断人是否可以到达,这里细节比较多,要注意
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 #define FFC(i,a,b) for(int i=a;i<=b;i++) 6 struct dtm{int x,y,t;}; 7 struct dtb{int x,y,t,mx,my;}; 8 int g[10][10],gg[10][10],t,m,n,x1,y1,x2,y2,d[][2]={1,0,-1,0,0,1,0,-1}; 9 bool v[10][10][4],f[10][10]; 10 bool checkmen(int x,int y){ 11 if(f[x][y]||x<1||x>n||y<1||y>m||gg[x][y]!=0)return 0; 12 return 1; 13 } 14 bool checkbox(int x,int y,int i){ 15 if(v[x][y][i]||x<1||x>n||y<1||y>m||g[x][y]==1)return 0; 16 return 1; 17 } 18 int bfs(int sx,int sy,int ex,int ey){ 19 if(ex<1||ex>n||ey<1||ey>m)return -1; 20 memset(f,0,sizeof(f)); 21 dtm s,o;s.x=sx,s.y=sy,s.t=0,f[sx][sy]=1; 22 queue<dtm>Q;Q.push(s); 23 while(!Q.empty()){ 24 o=Q.front();Q.pop(); 25 if(o.x==ex&&o.y==ey)return o.t; 26 for(int i=0;i<4;i++){ 27 int xx=o.x+d[i][0],yy=o.y+d[i][1]; 28 if(!checkmen(xx,yy))continue; 29 s.x=xx,s.y=yy,s.t=t+1,f[xx][yy]=1; 30 Q.push(s); 31 } 32 } 33 return -1; 34 } 35 int fuck(){ 36 memset(v,0,sizeof(v)); 37 dtb s,o;s.x=x1,s.y=y1,s.mx=x2,s.my=y2,s.t=0; 38 queue<dtb>Q;Q.push(s); 39 while(!Q.empty()){ 40 o=Q.front();Q.pop(); 41 if(g[o.x][o.y]==3)return o.t; 42 for(int i=0;i<4;i++){ 43 int xx=o.x+d[i][0],yy=o.y+d[i][1],ok; 44 if(!checkbox(xx,yy,i))continue; 45 gg[o.x][o.y]=2; 46 ok=bfs(o.mx,o.my,o.x-d[i][0],o.y-d[i][1]),gg[o.x][o.y]=0; 47 if(ok==-1)continue; 48 s.x=xx,s.y=yy,s.mx=o.x,s.my=o.y,s.t=o.t+1,v[xx][yy][i]=1; 49 Q.push(s); 50 } 51 } 52 return -1; 53 } 54 int main(){ 55 scanf("%d",&t); 56 while(t--){ 57 scanf("%d%d",&n,&m); 58 FFC(i,1,n)FFC(j,1,m){ 59 scanf("%d",&g[i][j]); 60 gg[i][j]=(g[i][j]==1?1:0); 61 if(g[i][j]==2)x1=i,y1=j; 62 if(g[i][j]==4)x2=i,y2=j; 63 } 64 printf("%d\n",fuck()); 65 } 66 return 0; 67 }