每次都要判断人能不能走到箱子的一边,然后推箱子
dp[i][j][k]记录从k方向推到i,j的最小格数
#include<stdio.h> #include<queue> #include<string.h> #define inf 0x3fffffff using namespace std; int dir[4][2]={0,1,1,0,0,-1,-1,0}; int map[10][10],dp[10][10][4],vis[10][10]; int n,m,Rx,Ry; struct op { int x,y,step; int rx,ry; }; int judge(int x,int y) { if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!=1) return 1; return 0; } int bfs1(int sx,int sy,int ex,int ey,int bx,int by)//判断人能不能走到箱子的一边 { memset(vis,0,sizeof(vis)); queue<op>Q; int x,y,i; op cur,next; cur.x=sx; cur.y=sy; vis[sx][sy]=1; Q.push(cur); while(!Q.empty()) { cur=Q.front(); Q.pop(); if(cur.x==ex&&cur.y==ey)return 1; for(i=0;i<4;i++) { next.x=x=cur.x+dir[i][0]; next.y=y=cur.y+dir[i][1]; if(judge(x,y)==0||(x==bx&&y==by)||vis[x][y]==1)continue; vis[x][y]=1; Q.push(next); } } return 0; } int bfs(int sx,int sy,int ex,int ey) { int i,x,y,rx,ry; queue<op>Q; op cur,next; cur.x=sx;cur.rx=Rx; cur.y=sy;cur.ry=Ry; cur.step=0; Q.push(cur); while(!Q.empty()) { cur=Q.front(); Q.pop(); if(cur.x==ex&&cur.y==ey) return cur.step; for(i=0;i<4;i++) { x=cur.x+dir[i][0]; y=cur.y+dir[i][1]; rx=cur.x-dir[i][0]; ry=cur.y-dir[i][1]; if(judge(x,y)==0||judge(rx,ry)==0)continue; if(bfs1(rx,ry,cur.rx,cur.ry,cur.x,cur.y)==0)continue; next.x=x; next.y=y; next.rx=cur.x; next.ry=cur.y; next.step=cur.step+1; if(next.step<dp[x][y][i]) { Q.push(next); dp[x][y][i]=next.step; } } } return -1; } int main() { int i,j,k,t,ex,ey,sx,sy; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=0;i<n;i++) for(j=0;j<m;j++) { scanf("%d",&map[i][j]); if(map[i][j]==4) Rx=i,Ry=j; if(map[i][j]==2) sx=i,sy=j; if(map[i][j]==3) ex=i,ey=j; } for(i=0;i<n;i++) for(j=0;j<m;j++) for(k=0;k<4;k++) dp[i][j][k]=inf; k=bfs(sx,sy,ex,ey); printf("%d\n",k); } return 0; }