每次都要判断人能不能走到箱子的一边,然后推箱子
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;
}