//题目意思很简单,但要拿下这道题必须明白以下几点;
//一;一个木块要想推动它,必须要保证他的前后都必须是道路;
//二;用一个dfs来搜索,是否能从人的位置,到达人将要推木块的位置,也就是木块的后方;其中人不能从此时木块的位置经过;
//三;用bfs神搜的过程中,为了防止超时,要将小的入队,这也是引入dp的原因;dp【I】【j】【k】表示从k方向推到(i,j)的最小格数;
//四,在bfs种,定义了rx,ry,变量,这样就可以把人目前的位置cur.rx,cur.ry,和将要到推木块后的位置rx,ry表示了出来。。否则,将很难表示;
另外要注意的是;
在bfs中由于,人和木块将要多次经过同一位置所以在这个搜索中不要进行标记,只要控制入队的条件就行了。。
在dfs中要进行标记,因为dfs的作用就是看能否找到一条道路,只有标记才不会重复寻找;
#include"stdio.h"
#include"string.h"
#include"queue"
#define inf 999999
int map[100][100];
int visit[100][100];
int dp[100][100][10];
int dir[4][2]={-1,0, 0,1, 0,-1, 1,0};
using namespace std;
int n,m,sx,sy,ex,ey,Rx,Ry;
struct point
{
int x,y,rx,ry;
int step;
};
int judge(int x,int y)
{
if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!=1)
return 1;
return 0;
}
int dfs(int sx,int sy,int ex,int ey,int tx,int ty)
{
memset(visit,0,sizeof(visit));
queue<point>q;
int x,y,i;
point cur,next;
cur.x=sx;
cur.y=sy;
visit[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==tx&&y==ty)||visit[x][y]==1)
continue;
visit[x][y]=1;
q.push(next);
}
}
return 0;
}
int bfs()
{
int i,x,y,rx,ry;
queue<point>q;
point 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++) //(cur.x,cur.y)木块的位置;
{
x=cur.x+dir[i][0]; //(x,y)木块前方的位置;
y=cur.y+dir[i][1];
rx=cur.x-dir[i][0]; //(rx,ry) 木块后方的位置;
ry=cur.y-dir[i][1];
if(judge(x,y)==0||judge(rx,ry)==0)
continue;
if(dfs(cur.rx,cur.ry,rx,ry,cur.x,cur.y))//这里分别是,人的位置,人将要打的位置,和木块的位置;
{
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,h;
scanf("%d",&k);
while(k--)
{
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]==3)
{
ex=i;ey=j;
}
if(map[i][j]==2)
{
sx=i;sy=j;
}
if(map[i][j]==4)
{
Rx=i;Ry=j;
}
for(h=0;h<4;h++)
dp[i][j][h]=inf;
}
printf("%d\n",bfs());
}
return 0;
}