1 条题解
-
0
思路与算法
每个非墙格是顶点,朝上下层、前后行、左右列的六个相邻格移动各花1分钟。用队列从S开始分层BFS:弹出本层全部格子,再把时间加1。第一次弹出E时输出当前时间;队列耗尽仍没到达则输出Trapped!。用动态字符数组保存地图并把已入队格标成墙,队列存扁平下标,不需要额外距离数组。
正确性说明
BFS初始层只含起点,对应距离0。假设第d层恰按最短距离d到达,所有新邻居经一条边可在d+1到达;任何更短路径都应在更早层发现它们,因此第一次入队的层数就是最短距离。每格只入队一次。首次弹出E得到最少分钟数;若队列为空,所有可达格都已探索,故E不可达,Trapped!正确。分层计数与队列中每个点的距离等价。
复杂度
设各组地图格数总和为V,每格至多检查6个方向。读入与地图初始化O(V),BFS与队列操作O(V),总时间O(V);单组字符地图和队列共O(LRC)空间。未使用固定三维数组,行列层范围只由实际输入决定。
易错点
三维共有六个方向,不能只检查平面四向。每组数据要重置起点、终点、地图、队列与计时。三个0是整份输入的结束标记。题面样例和提示明确要求Escaped in X minute(s).或Trapped!,不是只输出一个数字。空行可忽略,地图行本身不能被按空格拆成单格。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); size_t L, R, C; while (cin >> L >> R >> C && (L || R || C)) { size_t plane = R * C, total = L * plane, start = 0, finish = 0; vector<char> a(total); for (size_t z = 0; z < L; ++z) for (size_t y = 0; y < R; ++y) { string row; cin >> row; for (size_t x = 0; x < C; ++x) { size_t p = z * plane + y * C + x; a[p] = row[x]; if (row[x] == 'S') start = p; if (row[x] == 'E') finish = p; } } vector<size_t> q; q.reserve(total); q.push_back(start); a[start] = '#'; size_t head = 0, distance = 0; bool found = false; while (head < q.size() && !found) { size_t until = q.size(); while (head < until) { size_t p = q[head++]; if (p == finish) { found = true; break; } size_t z = p / plane, y = (p % plane) / C, x = p % C; auto visit = [&](size_t v) { if (a[v] != '#') { a[v] = '#'; q.push_back(v); } }; if (z) visit(p - plane); if (z + 1 < L) visit(p + plane); if (y) visit(p - C); if (y + 1 < R) visit(p + C); if (x) visit(p - 1); if (x + 1 < C) visit(p + 1); } if (!found) ++distance; } if (found) cout << "Escaped in " << distance << " minute(s).\n"; else cout << "Trapped!\n"; } }
- 1