/*
有两种做法:
一个不考虑走了回头路,因为数据是在是小,几乎不浪费时间
另一个是用贪心策略,先假设所有点剩余时间为0,只要该点剩余时间小于 上一点剩余时间-1
则修改remain值为remain-1再入队,否则不入队
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
#define CLR(c,v) (memset(c,v,sizeof(c)))
const int M = 30;
const int wall = 0;
const int road = 1;
const int start = 2;
const int end = 3;
const int reset = 4;
const int bomblimit = 6;
int revise[][2] = {{-1,0},
{0,-1},{0,1},
{1,0}};
int map[M][M];
int limit[M][M];
int n,m; // n*m
struct _P{
int x,y;
int step,remain;
_P(int x=-1,int y=-1,int step=0,int remain=0):x(x),y(y),step(step),remain(remain){}
bool operator <(const _P& p){
return step > p.step;
}
bool operator ==(const _P& p){
return (x==p.x) && (y==p.y);
}
}S,E;
typedef _P NEXT;
typedef _P NOW;
int BFS(){
queue<_P> que;
que.push(S);
while(!que.empty()){
NOW now = que.front();
que.pop();
if (now == E){
return now.step;
}
for (int i = 0 ; i < 4 ; i++){
int nx = now.x + revise[i][0];
int ny = now.y + revise[i][1];
int re = now.remain - 1;
if ( !(nx >= 0 && nx < n && ny >= 0 && ny < m ) || re <= 0)continue; // 出界 或 时间耗尽
if (map[nx][ny] == wall)continue;
NEXT next = NEXT( nx, ny, now.step+1, re );
if (map[nx][ny] == reset){
next.remain = bomblimit;
}
if (limit[nx][ny] < next.remain){ // 只有当剩余时间发现-1之后 还长的 才入队
limit[nx][ny] = next.remain;
que.push(next);
}
}
}
return -1;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("Input.txt","r",stdin);
//freopen("out.txt","w",stdout);
int Ncase,g;
cin >> Ncase;
while(Ncase -- ){
cin >> n >> m;
CLR(limit,0);
for (int i = 0 ; i <n ; i ++){
for (int j = 0 ; j < m ; j++){
scanf("%d",&g);
map[i][j] = g;
//limit[i][j] = 0; // 初始化
if (g == start){
S = _P(i,j,0,bomblimit);
limit[i][j] = bomblimit;
}else if(g == end){
E = _P(i,j,0,0);
map[i][j] = road;
}
}
}
cout << BFS() << endl;
}
return 0;
}
/*
一些变态的数据,不符合input
13
8 8
2 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 4 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 4 1 1 4 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 3
4 4
2 1 1 1
1 1 1 1
1 1 4 1
1 1 1 3
20 20
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 2 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3
5 8
1 2 1 1 1 1 1 4
1 0 0 0 1 0 0 1
1 4 1 0 1 1 0 1
1 0 0 0 0 3 0 1
1 1 4 1 1 1 1 1
2 8
2 1 1 1 1 1 1 0
0 0 1 4 1 1 1 3
8 8
2 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 4
4 4 4 4 4 4 4 3
2 1
2
3
3 3
2 1 1
1 1 0
1 1 3
4 8
2 1 1 0 1 1 1 0
1 0 4 1 1 0 4 1
1 0 0 0 0 0 0 1
1 1 1 4 1 1 1 3
1 2
2 3
3 3
2 4 1
1 4 1
1 4 3
1 8
2 4 4 4 4 4 4 3
1 8
2 0 0 0 0 0 0 3
8 8
2 1 0 0 0 0 0 0
1 4 1 0 0 0 0 0
0 1 4 1 0 0 0 0
0 0 1 4 1 0 0 0
0 0 0 1 4 1 0 0
0 0 0 0 1 4 1 0
0 0 0 0 0 1 4 1
0 0 0 0 0 0 1 3
8 8
2 1 4 4 0 0 0 0
1 0 1 0 0 0 0 0
0 1 4 1 0 4 0 0
4 0 1 0 1 0 0 0
0 0 1 1 4 1 1 4
0 0 4 0 1 0 1 0
0 0 0 0 0 1 1 1
0 0 0 0 4 0 1 3
*/