//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;}