题目描述
有一块 n×m 的地图,每个格子为水域(1)或陆地(0)。水域每天会向上下左右 四个方向扩散一格,被扩散到的陆地变为水域。求多少天后整个地图全部变为水域。
数据范围: 1 ≤ n, m ≤ 100。
示例
输入:
3 3
1 0 0
0 0 0
0 0 1
输出:
2
说明:两个角落是初始水域。第 1 天其相邻格被淹没,第 2 天中心格被淹没,全图变水域。
思路
- 这是经典的多源 BFS:把所有初始水域同时作为起点(都加入队列,距离为 0);
- BFS 一层一层向外扩散,每个格子的最短距离就是它"第几天被淹没";
- 答案 = 所有格子距离的最大值(即离水域最远的格子被淹没的时间);
- 若初始全是水域,答案为 0。
C 代码
#include <stdio.h>
#define MAXN 105
int dist[MAXN][MAXN]; /* -1 表示未淹没,否则为被淹没的天数 */
int qx[MAXN * MAXN], qy[MAXN * MAXN]; /* 手写循环队列存坐标 */
int n, m;
const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = { 0, 0, -1, 1};
int main(void)
{
if (scanf("%d %d", &n, &m) != 2) return 0;
int head = 0, tail = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int x;
scanf("%d", &x);
dist[i][j] = -1;
if (x == 1) { /* 所有初始水域作为多源起点 */
dist[i][j] = 0;
qx[tail] = i; qy[tail] = j; tail++;
}
}
}
int ans = 0;
while (head < tail) {
int x = qx[head], y = qy[head]; head++;
if (dist[x][y] > ans) ans = dist[x][y];
for (int k = 0; k < 4; k++) {
int nx = x + dx[k], ny = y + dy[k];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (dist[nx][ny] != -1) continue; /* 已淹没过 */
dist[nx][ny] = dist[x][y] + 1;
qx[tail] = nx; qy[tail] = ny; tail++;
}
}
/* 拓展:若题目允许存在无法淹没的格子(如障碍物),
此处应再扫描一遍,存在 dist == -1 则输出 -1 */
printf("%d\n", ans);
return 0;
}
复杂度: 时间 O(n×m),空间 O(n×m)。每个格子最多入队一次,保证距离正确。