题目链接:点击这里
本题可以看作一道有多个起始状态的 flood-fill 问题。我们把矩阵 中每一个 1 都看作起点,整个矩阵的所有位置都可以通行,对于每个位置,在从任何一个起点出发都可以的情况下,求到达该位置所需要的最少步数(也就是距离该位置最近的起点的距离)。
在这种具有多个等价的起始状态的问题中,我们只需要在 BFS 开始之前把这些起始状态全部插入队列。根据 BFS 逐层搜索的性质,BFS 的过程就相当于每个起点先扩展 1 层,再扩展 2 层,3 层,依此类推。所以当每个位置 第一次被访问时,就相当于距离它最近的那个起点扩展到了它,此时从那个起点到 经历的步数就是最短距离 。
输入的 01 矩阵没有空格,所以用字符串读入。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N = 1010, M = N * N;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int n, m;
char g[N][N];
int d[N][N];
PII q[M];
void bfs()
{
int hh = 0, tt = -1;
memset(d, -1, sizeof d);
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j)
if(g[i][j] == '1')
q[++tt] = {i, j}, d[i][j] = 0;
while(hh <= tt)
{
PII t = q[hh++];
for(int i = 0; i < 4; ++i)
{
int nx = t.x + dx[i], ny = t.y + dy[i];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if(d[nx][ny] != -1) continue;
q[++tt] = {nx, ny};
d[nx][ny] = d[t.x][t.y] + 1;
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i) scanf("%s", g[i]);
bfs();
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < m; ++j) printf("%d ", d[i][j]);
puts("");
}
return 0;
}