265-2
1096. 地牢大师(BFS+三维数组)
你现在被困在一个三维地牢中,需要找到最快脱离的出路!
地牢由若干个单位立方体组成,其中部分是不含岩石障碍的空单元格,可以直接通过;部分包含岩石障碍,无法通过。
向北、向南、向东、向西、向上或向下移动一个单元均需要一分钟。
你不能沿对角线移动,地牢边界都是坚硬的岩石,你不能走出边界范围。
请问,你有可能逃脱吗?如果可以,需要多长时间?
输入格式
输入包含多组测试数据。
每组数据第一行包含三个整数 L, R, C,分别表示地牢的层数,以及每一层的行数和列数。
接下来是 L 个矩阵,每个矩阵有 R 行 C 列,用来表示每一层地牢的具体状况。
每个字符描述一个地牢单元的状态:“#”表示岩石障碍,“.”表示空单元格,“S”表示你的起始位置,“E”表示终点。
每一个字符矩阵后面都会有一个空行。
当输入一行为“0 0 0”时,表示输入终止。
输出格式
每组数据输出一个结果,每个结果占一行。
如果能够逃脱地牢,则输出“Escaped in x minute(s).”,其中 x 为逃脱所需的最短时间。
如果不能逃脱地牢,则输出“Trapped!”。
数据范围
1 ≤ L, R, C ≤ 100
输入样例:
cpp
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0输出样例:
cpp
Escaped in 11 minute(s).
Trapped!分析
- 该地牢是立体的,故需要使用三维数组构建模型。
- 要求第一次搜索到的路径即为最短时间,因此考虑使用 BFS。
- 记录“S”和“E”的位置,“S”是搜索的起点,“E”是搜索的终点。
- 搜索过程中每个位置需要向六个方向扩展,需要定义偏移量数组。
- 扩展的点需要满足:不越界、未被访问过、不是障碍“#”。
代码
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int l, r, c; // 地牢参数
int px, py, pz, ex, ey, ez; // (px, py, pz) 为 S 的位置,(ex, ey, ez) 为 E 的位置
char mp[N][N][N]; // 记录地牢
int ans[N][N][N]; // 存储答案
bool vis[N][N][N]; // 记录该点是否被访问过
struct point { // 点的坐标
int x, y, z;
};
queue<point> st; // 搜索队列
int dx[] = {1, -1, 0, 0, 0, 0}, dy[] = {0, 0, 1, -1, 0, 0}, dz[] = {0, 0, 0, 0, 1, -1}; // 偏移量数组
int bfs(){
while(!st.empty()){ // 当队列不为空时,扩展搜索当前节点
auto p = st.front();
for(int i = 0; i < 6; i++){
int m_x = p.x + dx[i], m_y = p.y + dy[i], m_z = p.z + dz[i]; // 偏移之后的点的坐标
if(m_x <= l && m_y <= r && m_z <= c && m_x >= 1 && m_y >= 1 && m_z >= 1 && !vis[m_x][m_y][m_z] && mp[m_x][m_y][m_z] != '#'){ // 判断条件
vis[m_x][m_y][m_z] = 1; // 更新该点走过的状态
ans[m_x][m_y][m_z] = ans[p.x][p.y][p.z] + 1; // 更新偏移后的点距离S的步骤
if(mp[m_x][m_y][m_z] == 'E') return ans[m_x][m_y][m_z]; // 搜到E直接返回答案
st.push({m_x, m_y, m_z}); // 将该点入队,继续扩展搜索
}
}
st.pop(); // 队头扩展搜索完毕后出队
}
return 0; // 所有的点扩展搜索完后若还未返回搜到E,说明无解
}
int main(){
while(cin >> l >> r >> c && l && r && c){ // 多实例读入
// 还原数据
memset(ans, 0, sizeof(ans));
memset(mp, 0, sizeof(mp));
memset(vis, 0, sizeof(vis));
while(!st.empty()){
st.pop();
}
// 读入迷宫
for(int i = 1; i <= l; i++){
for(int j = 1; j <= r; j++){
for(int k = 1; k <= c; k++){
cin >> mp[i][j][k];
if(mp[i][j][k] == 'S') px = i, py = j, pz = k; // 记录起点S的坐标
if(mp[i][j][k] == 'E') ex = i, ey = j, ez = k; // 记录终点E的坐标
}
}
}
vis[px][py][pz] = 1; // 标记S已经走过
st.push({px, py, pz}); // S点入队
int cnt = bfs(); // 调用BFS搜索
if(cnt != 0) printf("Escaped in %d minute(s).\n", cnt);
else cout << "Trapped!" << endl;
return 0;
}
}