用BFS让箱子走一遍即可。
其中判断箱子能否往前走,除了看它前面是否为墙,还要判断人能不能到它后面的方格。
还有标记状态,箱子和人有一个位置不同,便是不同的状态。我用的哈希判重,其实开个四维数组也行,毕竟数据范围不大。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define FOR(i,s,t) for(int i = (s) ; i <= (t) ; ++i )
#define lchild o<<1
#define rchild o<<1|1
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=10007;
int dir[4][2]={0,-1,0,1,-1,0,1,0};
int t,m,n,ans;
int mp[10][10];
struct node
{
int bx,by,px,py;//箱子的坐标和人的坐标
int step;
inline int operator==(const node & a)
{
if( bx!=a.bx )return false;
if( by!=a.by )return false;
if( px!=a.px )return false;
if( py!=a.py )return false;
return true;
}
bool friend operator<(node a,node b)
{
return a.step>b.step;
}
};
node start;
vector <node> v[maxn];
int myhash(node a){
return (a.bx * 11 + a.by*111 + a.px*1111 + a.py*11111 ) % maxn;
}
bool ok(int x,int y){
if( x<0 || x>=m )return false;
if( y<0 || y>=n )return false;
if( mp[x][y]==1 )return false;
return true;
}
bool visit(node a){
int ha = myhash(a);
int num = v[ha].size();
for(int i=0 ; i<num ; ++i){
if( v[ha][i] == a ){
//printf("has vised this state.\n");
return true;
}
}
v[ha].push_back(a);
return false;
}
bool cango(node a,int sx,int sy){
//printf("box : %d,%d ; if can go to %d,%d \n",a.bx,a.by,sx,sy );
//bfs判断人能否到达mp[sx][sy]
node now=a,next;
bool vis[10][10];
memset(vis,0,sizeof vis);
vis[now.px][now.py]=1;
queue<node>q2;
q2.push(now);
while(!q2.empty()){
now=q2.front();
q2.pop();
//printf("now peo:: %d,%d\n",now.px,now.py );
if(now.px==sx && now.py==sy){
return true;
}
for(int i=0;i<4;++i){
int nx = now.px+dir[i][0];
int ny = now.py+dir[i][1];
if( !ok(nx,ny) )continue;
if( vis[nx][ny])continue;
if( nx == now.bx && ny == now.by )continue;
vis[nx][ny]=1;
next.bx=now.bx;
next.by=now.by;
next.px=nx;
next.py=ny;
next.step=now.step+1;
//printf(" next peo:: %d,%d\n",next.px,next.py );
q2.push(next);
}
}
return false;
}
int bfs(){
node now = start,next ;
priority_queue <node> q;
q.push(now);
visit(now);
while( !q.empty() ){
now=q.top();
q.pop();
//printf("now box:: %d,%d\n",now.bx,now.by );
if( mp[now.bx][now.by]==3 ){
return now.step;
}
for(int i=0;i<4;++i){
int nx = now.bx + dir[i][0];
int ny = now.by + dir[i][1];
if( !ok(nx,ny) )continue;
int lx = now.bx - dir[i][0];
int ly = now.by - dir[i][1];
if( !ok(lx,ly) )continue;
if( cango(now,lx,ly) ){
next.bx=nx;
next.by=ny;
next.px=now.bx;
next.py=now.by;
next.step=now.step+1;
if( !visit(next) ) q.push(next);
}
}
}
return -1;
}
int main()
{
//freopen("in.txt","r",stdin);
Ri(t);
while(t--){
for(int i=0;i<maxn;++i)v[i].clear();
Ri(m);Ri(n);
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
Ri( mp[i][j] );
if(mp[i][j]==2){
start.bx=i;
start.by=j;
}else if(mp[i][j]==4){
start.px=i;
start.py=j;
start.step=0;
}
//printf("%d ",mp[i][j] );
}
//printf("\n");
}
ans=bfs();
printf("%d\n",ans );
}
return 0;
}