poj-2251 Dungeon Master 三维BFS

时间:2022-03-21 16:17:39

题目链接

poj-2251 Dungeon Master

题目

Dungeon Master
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 42166   Accepted: 15969

Description

You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides. 

Is an escape possible? If yes, how long will it take? 

Input

The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size). 
L is the number of levels making up the dungeon. 
R and C are the number of rows and columns making up the plan of each level. 
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a '#' and empty cells are represented by a '.'. Your starting position is indicated by 'S' and the exit by the letter 'E'. There's a single blank line after each level. Input is terminated by three zeroes for L, R and C.

Output

Each maze generates one line of output. If it is possible to reach the exit, print a line of the form 
Escaped in x minute(s).

where x is replaced by the shortest time it takes to escape. 
If it is not possible to escape, print the line 
Trapped!

Sample Input

3 4 5
S....
.###.
.##..
###.#

#####
#####
##.##
##...

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0

Sample Output

Escaped in 11 minute(s).
Trapped!

Source

题意

3D迷宫,刚开始输入3个数据l、r、c,l表示迷宫的层数,r跟c表示一层迷宫的行与列数。迷宫'#'表示墙'.'表示路'S'表示开始位置'E'表示迷宫出口。迷宫的每个位置有6种移动方式:上下左右前后。所以说是3D迷宫,也就是说每层与每层之间可以任意移动,比如我从第一层的(1,1)位置可以移动到第二层的(1,1)位置,仍然只花费1分钟。要求给出出迷宫的最短时间,或者给出无法走出迷宫的结果。输出格式如Sample Output的样例。

题解

对于比较熟悉搜索的同学而言,该题就非常简单了,不过就是正常的BFS只是移动方式由常规的4中变成了6种——因为有n层迷宫,迷宫之间也能移动。但也只是多一层循环,将二维数组变成三维数组而已。

对于刚接触搜索的同学博主谈一下个人看法:

1.该题要用BFS而不是DFS。因为题目要求的是最短路径,DFS是要搜索全图并且对每种结果的最终路径长度进行比较,而BFS在搜索到第一种结果的时候就能得到最短路径。速度上是有明显优势的(当然,无解的情况大家都一样搜了全部可能)。

2.BFS的写法基本类似模板了,利用队列,只是数组变成三维。写一个结构体来描述所在迷宫的位置,go数组也要开成6*3的,因为有3种坐标,6种走法。

3.check函数来判断移动是否合法,这里主要,要用||来判定,反正博主是用&&TLE,||却47ms,希望了解真相的同学能评论一下,不胜感激!

满足以上三点就能写出代码了,整体还是不难,只是第一次见的话可能让三维的情况坑一下。

C++ 代码 47ms

#include<iostream>
#include<vector>
#include<string>
#include<math.h>
#include<algorithm>
#include<map>
#include<utility>
#include<queue>
#define TIME std::ios::sync_with_stdio(false)
#define LL long long
#define MAX 310
#define INF 0x3f3f3f3f

using namespace std;

char maps[31][31][31];
int step[31][31][31];
int l, r, c;
int go[6][3] = { { 0,0,1 },{ 0,0,-1 },{ 0,1,0 },{ 0,-1,0 },{ 1,0,0 },{ -1,0,0 } };

struct node {
	int l, r, c, ans;
};

int check(int x, int y, int z)
{
	if (x <= 0 || y <= 0 || z <= 0 || x > l || y > r || z > c) {
		return 1;
	}else {
		if (maps[x][y][z] == '#') {
			return 1;
		}else {
			if (step[x][y][z]) {
				return 1;
			}
		}		
	}
	return 0;
}

int bfs(queue<node> que) {
	while (!que.empty()) {
		node now = que.front();
		que.pop();
		if (maps[now.l][now.r][now.c] == 'E') return now.ans;
		for (int i = 0; i < 6; i++) {
			node next;
			next.l = now.l + go[i][0];
			next.r = now.r + go[i][1];
			next.c = now.c + go[i][2];
			next.ans = now.ans;
			if (check(next.l, next.r, next.c)) continue;
			step[next.l][next.r][next.c] = 1;
			next.ans++;
			que.push(next);
		}
	}
	return 0;
}

int main() {
	TIME;
	while (cin >> l >> r >> c) {
		if (l == 0 && r == 0 && c == 0) break;
		queue<node> que;
		for (int i = 1; i <= l; i++) {
			for (int j = 1; j <= r; j++) {
				for (int k = 1; k <= c; k++) {
					cin >> maps[i][j][k];
					if (maps[i][j][k] == 'S') {
						node node_end;
						node_end.l = i;
						node_end.r = j;
						node_end.c = k;
						node_end.ans = 0;
						que.push(node_end);
					}
				}
			}
		}
		memset(step, 0, sizeof(step));
		int ans = bfs(que);
		if (ans == 0) {
			cout << "Trapped!" << endl;
		}
		else {
			cout << "Escaped in " << ans << " minute(s)." << endl;
		}
	}

	system("pause");
	return 0;
}