最近出口
解题思路
这道题目要求我们计算网格中每个可通行的走廊位置到最近紧急出口的最短距离。解题的关键在于:
-
多源广度优先搜索(BFS):由于网格中可能有多个紧急出口(E),我们需要从所有E同时开始搜索,计算每个位置到最近E的距离。
-
距离传播:从每个E出发,逐步向外扩展,记录每个位置到E的最短步数。使用队列来管理待处理的网格位置。
-
障碍处理:墙壁(#)不可通行,遇到墙壁时需要跳过。
-
结果输出:最后输出时,保持墙壁和紧急出口不变,将走廊位置替换为计算得到的最短距离。
代码注释
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e3+5;
char M[N][N], ans[N][N]; // M存储原始网格,ans存储结果(实际上未使用)
int dist[N][N], n, m; // dist存储每个位置到最近E的距离,n和m是网格的行列数
int d[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; // 四个移动方向:上、下、左、右
struct node{ int x, y; }; // 用于BFS的节点结构,存储坐标
queue<node> q; // BFS队列
int main() {
// 输入网格大小和内容
cin >> n >> m;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> M[i][j]; // 读取网格内容
ans[i][j] = M[i][j]; // 复制到ans数组(实际上未使用)
dist[i][j] = -1; // 初始化距离为-1(表示未访问)
}
}
// 多源BFS初始化:将所有E的位置加入队列,并设置距离为0
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(M[i][j] == 'E') {
dist[i][j] = 0; // E到自身的距离为0
q.push({i, j}); // 加入队列
}
}
}
// BFS过程
while(!q.empty()) {
node now = q.front(); // 取出队列头部
q.pop();
// 检查四个方向
for(int i = 0; i < 4; i++) {
int tx = now.x + d[i][0]; // 计算新位置的x坐标
int ty = now.y + d[i][1]; // 计算新位置的y坐标
// 如果新位置在网格内、是走廊且未被访问过
if(tx >= 1 && tx <= n && ty >= 1 && ty <= m &&
M[tx][ty] == '.' && dist[tx][ty] == -1) {
dist[tx][ty] = dist[now.x][now.y] + 1; // 更新距离
q.push({tx, ty}); // 加入队列继续扩展
}
}
}
// 输出结果
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(dist[i][j] == -1) cout << '#'; // 墙壁保持原样
else if(dist[i][j] == 0) cout << 'E'; // 紧急出口保持原样
else cout << dist[i][j]; // 走廊输出距离
}
cout << endl; // 换行
}
return 0;
}
关键点说明
-
多源BFS:从所有E同时开始搜索,确保每个位置找到的是最近的E的距离。
-
距离更新:每次从队列中取出一个位置,检查其四个邻居,如果邻居是走廊且未被访问过,则更新其距离并加入队列。
-
边界检查:在检查邻居时,需要确保新位置在网格范围内(1 ≤ x ≤ n,1 ≤ y ≤ m)。
-
输出处理:根据dist数组的值,决定输出墙壁、紧急出口或距离值。
这个算法的时间复杂度是O(HW),因为每个网格位置最多被处理一次,适用于题目给定的约束条件(H,W ≤ 1000)。