//http://ac.jobdu.com/problem.php?cid=1040&pid=85
#include <stdio.h>
#include <queue>
using namespace std;
struct N //状态结构体
{
int x,y,z; //位置坐标
int t; //所需时间
};
bool mark[51][51][51]; //标记数组,扩展出(x,y,z)之后记为true,再次扩展出来后直接丢弃
int maze[51][51][51]; //保存立方体信息
queue<N> Q; //队列中元素是状态(x,y,z,t)
int go[][3]= //坐标变换数组,(x,y,z)->(x+go[i][0],y+go[i][1],z+go[i][2])
{
1,0,0,
-1,0,0,
0,1,0,
0,-1,0,
0,0,1,
0,0,-1,
};
int BFS(int a,int b,int c) //广度优先搜索,返回到达目的点的最少耗时
{
while (Q.empty()==false) //当仍有元素可以扩展时循环
{
N now=Q.front();
Q.pop();
for (int i=0;i<6;i++) //依次扩展6个相邻节点
{
int nx=now.x+go[i][0];
int ny=now.y+go[i][1];
int nz=now.z+go[i][2];
if (nx<0 || nx>=a || ny<0 || ny>=b || nz<0 || nz>=c )
{
continue; //若新坐标再正方体外,丢弃该坐标
}
if (maze[nx][ny][nz]==1)
{
continue; //若新坐标为墙,丢弃
}
if (mark[nx][ny][nz]==true)
{
continue; //若该状态已经得到过,则丢弃,因为时间必定大于上次
}
N tmp; //新状态
tmp.x=nx;
tmp.y=ny;
tmp.z=nz;
tmp.t=now.t+1;
Q.push(tmp); //该状态放入队列,因为广度优先按照被查找到的顺序依次扩展下一层
mark[nx][ny][nz]=true; //标记该坐标
if (nx==a-1 && ny==b-1 && nz==c-1)
{
return tmp.t; //若是终点,返回其耗时
}
}
}
return -1; //所有状态都被查找完,仍得不到所需坐标,返回-1
}
int main()
{
int T,i,j,k;
scanf("%d",&T);
while (T--)
{
int a,b,c,t;
scanf("%d%d%d%d",&a,&b,&c,&t);
for(i=0;i<a;i++) //初始化
{ for (j=0;j<b;j++)
{
for (k=0;k<c;k++)
{
scanf("%d",&maze[i][j][k]);//输入立方体信息
mark[i][j][k]=false; //初始化标记数组
}
}
}
while (Q.empty()==false)
{
Q.pop(); //清空队列,防止上组数据遗留
}
mark[0][0][0]=true; //标记起点
N tmp;
tmp.t=tmp.x=tmp.y=tmp.z=0; //初始状态
Q.push(tmp);
int rec=BFS(a,b,c); //广度优先搜索
if (rec<=t)
{
printf("%d\n",rec);
}
else
{
printf("-1\n");
}
}
return 0;
}