Dungeon Master
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(无语了,#连载一排没法显示,不做了,样例在链接里有)
Sample Output
Escaped in 11 minute(s).
Trapped!
BFS进一步训练,读题可以明白,
#代表没法走
.代表可以走
S代表起点
E代表终点
在一个三维的空间里规定了长宽高,找出最短从S到达E的步数
先来一波BFS三连:结构体、边界、初始化队列
1、结构体的定义
显然,结构体应该包括长宽高(理解成层数,行数,列数比较好)和到达该点的最短步数
typedef struct {
int floor,x,y;//坐标,
int time;//深度
}H;
H h1, h2;//搬运工和检查员
2、边界的规定
退出搜索的边界:
题意可知,当找到E所在的坐标的时候,停止搜索,准备进行返回
不合规操作的判定:
搜索出了输入的范围,比如跑到-1层啥的
3、队列的初始化
显然,在输入迷宫的同时需要找到E和S,这是两个不同的元素(特殊元素处理),需要把S的坐标存到全局变量(START)进行初始化
三连之后就应该研究操作了
很明显的,包括了上下左右前后(层数±1、行数±1、列数±1)因为我直接把S存到了全局变量中去,所以BFS根本就没带参数(果然带不带参数不是定死了的,是根据实际情况来的)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
inline ll read() {//读入挂
ll c = getchar(), Nig = 1, x = 0;
while (!isdigit(c) && c != '-')c = getchar();
if (c == '-')Nig = -1, c = getchar();
while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
return Nig * x;
}
inline void Out(ll a)
{//输出挂
if (a < 0)putchar('-'), a = -a;
if (a >= 10)Out(a / 10);//记得这是a>=10,让坑坏了
putchar(a % 10 + '0');
}
typedef struct {
int floor,x,y;//坐标
int time;//深度
}H;
H h1, h2;//搬运工和检查员
H START, END;//全局边界
bool jud[37][37][37];//标记状态是否存在
char T[37][37][37];//开大一点,可以用0做边界,不用担心数组越界的问题
queue<H>Q;//队列
H step[7] = {{0,0,0,0},{1,0,0,1},{-1,0,0,1},{0,1,0,1},{0,-1,0,1},{0,0,1,1},{0,0,-1,1} };//六步操作,分别是上下层,上下行,左右列
int BFS() {//不用参数做边界
h2.floor = START.floor;
h2.x = START.x;
h2.y = START.y;
h2.time = 0;
Q.push(h2);//用起点初始化队列
while (!Q.empty()) {
h1 = Q.front();
Q.pop();
if (h1.floor == END.floor && h1.x == END.x && h1.y == END.y) {//到达终点
while (!Q.empty()) {
Q.pop();//清空
}
return h1.time;//返回走的步数
}
//上一层
h2.floor = h1.floor + step[1].floor;
h2.x = h1.x + step[1].x;
h2.y = h1.y + step[1].y;
h2.time = h1.time + step[1].time;
if (!jud[h2.floor][h2.x][h2.y]&& T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
Q.push(h2);
jud[h2.floor][h2.x][h2.y] = true;
}
//下一层
h2.floor = h1.floor + step[2].floor;
h2.x = h1.x + step[2].x;
h2.y = h1.y + step[2].y;
h2.time = h1.time + step[2].time;
if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
Q.push(h2);
jud[h2.floor][h2.x][h2.y] = true;
}
//上一行
h2.floor = h1.floor + step[3].floor;
h2.x = h1.x + step[3].x;
h2.y = h1.y + step[3].y;
h2.time = h1.time + step[3].time;
if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
Q.push(h2);
jud[h2.floor][h2.x][h2.y] = true;
}
//下一行
h2.floor = h1.floor + step[4].floor;
h2.x = h1.x + step[4].x;
h2.y = h1.y + step[4].y;
h2.time = h1.time + step[4].time;
if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
Q.push(h2);
jud[h2.floor][h2.x][h2.y] = true;
}
//右一列
h2.floor = h1.floor + step[5].floor;
h2.x = h1.x + step[5].x;
h2.y = h1.y + step[5].y;
h2.time = h1.time + step[5].time;
if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
Q.push(h2);
jud[h2.floor][h2.x][h2.y] = true;
}
//左一列
h2.floor = h1.floor + step[6].floor;
h2.x = h1.x + step[6].x;
h2.y = h1.y + step[6].y;
h2.time = h1.time + step[6].time;
if (!jud[h2.floor][h2.x][h2.y] && T[h2.floor][h2.x][h2.y]) {//jud没标记而且不越界
Q.push(h2);
jud[h2.floor][h2.x][h2.y] = true;
}
}
return -1;
}
int main() {
int floor, x, y;
while (floor = read() , x = read(), y = read()) {
if (floor == x && x == y && y == 0)
break;
char temp;
for (int i = 1; i <= floor; i++) {//用1开始是为了用0做边界
for (int j = 1; j <= x; j++) {
for (int k = 1; k <= y; k++) {
temp = getchar();
if (temp == 'S') {//找到起点并数据标记到START
START.floor = i;
START.x = j;
START.y = k;
}
if(temp == 'E') {//终点,数据标记到END
END.floor = i;
END.x = j;
END.y = k;
}
if (temp == '#')
jud[i][j][k] = true;//提前标记不可到达
T[i][j][k] = temp;//存入数组
}
getchar();//每一列输入完毕都要吞掉回车,这一行要尤其注意,这题对getchar()的要求还挺高
}
getchar();//每一层输入完毕也要吞掉回车
int Temp = BFS();
if (Temp==-1) {
cout << "Trapped!" << endl;
}
else {
cout << "Escaped in " << Temp << " minute(s)." << endl;
}
memset(jud,0,sizeof(jud));//多组输入的必要操作
memset(T,0,sizeof(T));//避免影响后续数据的判断
}
}