1 #include<iostream>
2 #include<queue>
3 #include<cstring>
4 using namespace std;
5 int room[10][10];//房间布置
6 int n,m,res;//行、列 ,res为最终结果
7 struct node
8 {
9 int x,y,step;//x,y为坐标,step指箱子走过的路
10 }per,fin,box;//分别指人,终点,以及箱子
11 bool pvis[10][10];//人能到的位置
12 bool pbvis[10][10][10][10];//判重
13 int rx[]={0,0,1,-1};
14 int ry[]={1,-1,0,0};
15 void bfs_per()//找出人当前可以走的位置
16 {
17 queue<node>qper;
18 memset(pvis,false,sizeof(pvis));
19 qper.push(per);
20 node cur,next;
21 while(!qper.empty())
22 {
23 cur=qper.front();
24 qper.pop();
25 pvis[cur.x][cur.y]=true;
26 for(int i=0;i<4;i++)
27 {
28 next.x=cur.x+rx[i];
29 next.y=cur.y+ry[i];
30 if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m)//在界内
31 if(room[next.x][next.y]==0)//可走
32 if(!pvis[next.x][next.y])
33 qper.push(next);
34 }
35 }
36 }
37 void bfs_box()//找出箱子可移动的最短路径
38 {
39 queue<node>qbox;
40 qbox.push(box);
41 qbox.push(per);
42 node cur,next;
43 while(!qbox.empty())
44 {
45 cur=qbox.front();//box所在位置
46 qbox.pop();
47 per=qbox.front();//人的位置
48 qbox.pop();
49 if(cur.x==fin.x&&cur.y==fin.y)
50 {
51 if(res==-1||cur.step<res)
52 res=cur.step;
53 return ;
54 }
55 pbvis[cur.x][cur.y][per.x][per.y]=true;
56 room[cur.x][cur.y]=2;//箱子人是不能走的
57 bfs_per();//人可以到达的位置
58 room[cur.x][cur.y]=0;//回溯
59 for(int i=0;i<4;i++)
60 {
61 next.x=cur.x+rx[i];
62 next.y=cur.y+ry[i];
63 next.step=cur.step+1;
64 if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m) //在界内
65 if(room[next.x][next.y]==0)//箱子位置可达
66 if(pvis[cur.x-rx[i]][cur.y-ry[i]])//人能到箱子的反方向
67 if(!pbvis[next.x][next.y][cur.x][cur.y])//判重防止TLE
68 {
69 qbox.push(next);//箱子当前的位置
70 qbox.push(cur);// 人当前的位置
71 }
72 }
73 }
74 }
75 int main()
76 {
77 int T;
78 cin>>T;
79 while(T--)
80 {
81 cin>>n>>m;
82 for(int i=0;i<n;i++)
83 for(int j=0;j<m;j++)
84 {
85 cin>>room[i][j];
86 if(room[i][j]==2)
87 box.x=i,box.y=j,box.step=0;//初始化
88 else if(room[i][j]==3)
89 fin.x=i,fin.y=j,room[i][j]=0;//处理成可以走的地方
90 else if(room[i][j]==4)
91 per.x=i,per.y=j,room[i][j]=0;
92 }
93 res=-1;
94 memset(pbvis,false,sizeof(pbvis));//都没有访问过
95 bfs_box();
96 printf("%d\n",res);
97 }
98 return 0;
99 }