题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1253
//这个题我MLE了好几次,就意识到剪枝的必要性
//改进后的代码
#include <iostream>
#include <queue>
using namespace std;
int dir[6][3] = {{0,0,1},{0,1,0},{0,0,-1},{0,-1,0},{1,0,0},{-1,0,0}};
bool Map[50][50][50];//保存地图
struct Pos {
int x, y, z, t;
};
int main()
{
int k, a, b, c, time, wall;
int x, y, z, i, j, p;
bool flag;
queue<Pos> q;
Pos v, temp;
scanf("%d", &k);
while(k--) {
flag = false;
wall = 0;
scanf("%d%d%d%d",&a, &b, &c, &time);
for (i = 0; i < a; i++)
for (j = 0; j < b; j++)
for (p = 0; p < c; p++) {
scanf("%d", &Map[i][j][p]);
if (Map[i][j][p] != 0) wall ++;
}
if (a*b*c-wall < a+b+c-2 || time < a+b+c-3) {puts("-1"); continue;}
//bfs
while (!q.empty()) q.pop();
v.x = 0; v.y = 0; v.z = 0; v.t = 0;//起点
q.push(v);//起点入队
while (!q.empty()) {
v = q.front(); q.pop();
if (v.t > time) break;
if (v.x == a-1 && v.y == b-1 && v.z == c-1 && v.t <= time) { flag = true; break; }
for (i = 0; i < 6; i++) { //搜索下一层的节点
x = v.x + dir[i][0];
y = v.y + dir[i][1];
z = v.z + dir[i][2];
if (!Map[x][y][z] && x >= 0 && x < a && y >= 0 && y < b && z >= 0 && z < c)
{
temp.x = x; temp.y = y; temp.z = z; temp.t = v.t+1;
if (temp.t + a-1-temp.x + b-1-temp.y + c-1-temp.z > time) {//剪枝
Map[temp.x][temp.y][temp.z] = 1; continue;
}
q.push(temp);
Map[temp.x][temp.y][temp.z] = 1;//标记掉已访问的点
}
}
}
if (flag) printf("%d\n", v.t);
else puts("-1");
}
return 0;
}