acwing-173. 矩阵距离

考点

  • BFS

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 50;
// 0~3左右上下
const int dx[4] = {0, 0, -1, 1}, dy[4] = {-1, 1, 0, 0};
char s[maxn][maxn];
int n, m, d[maxn][maxn];

struct node {
int x_, y_;
node(int x = 0, int y = 0) : x_(x), y_(y) {}
};
queue<node> q;

bool valid(int x, int y) { return x >= 1 && y >= 1 && x <= n && y <= m; }

void bfs() {
while (!q.empty()) {
node u = q.front();
q.pop();
for (int i = 0; i < 4; ++i) {
int x = u.x_ + dx[i], y = u.y_ + dy[i];
if (!valid(x, y) || ~d[x][y]) continue;
d[x][y] = d[u.x_][u.y_] + 1;
q.emplace(x, y);
}
}
}

int main() {
cin >> n >> m;
memset(d, -1, sizeof(d));
// 必须用字符串或字符,整数型会被吞
for (int i = 1; i <= n; ++i) scanf("%s", s[i] + 1);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (s[i][j] == '1') q.emplace(i, j), d[i][j] = 0;
}
}
bfs();
for (int i = 1; i <= n; ++i, cout << endl) {
for (int j = 1; j <= m; ++j) {
cout << d[i][j] << " ";
}
}
return 0;
}

思路

有多个起始状态的flood-fill问题,矩阵中每一个1都看作起点,整个矩阵的所有位置都可以通行;

对于每个位置,在从任何一个起点出发都可以的情况下,求到达该位置所需要的最小步数

(也就是距离该位置最近的起点的距离)


根据BFS逐层搜索的性质,BFS的过程就相当于每个起点先扩展1层、再扩展2层、3层,以此类推。

所以当每个位置(x, y)第一次被访问时,就相当于距离它最近的那个起点扩展到了它,

此时从那个起点到(x, y)经历的步数就是最短距离B[x][y]