hdoj1253 胜利大逃亡

题目链接: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;
}


你可能感兴趣的:(hdoj1253 胜利大逃亡)