Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)-C题解
题目大意
一个 \(H\) 行和 \(W\) 列的网格图。\((i, j)\) 表示从上到下第 \(i\) 行和从左到下第 \(j\) 列的单元格。
每个单元格用字符 \(S_{i,j}\) 表示。如果 \(S_{i,j}\) 为#,则该单元格有一个障碍物;如果 \(S_{i,j}\) 是 . 则该单元格是空的;如果 \(S_{i,j}\) 为 H,则该单元网格图上安装了加湿器。
如果在不穿过障碍的情况下,可以从至少一个放了加湿器的单元格通过最多 \(D\) 次向上、向下、向左或向右移动到达某个单元个,则认为该单元格已加湿。注意:任何有加湿器的单元格都是加湿的。
请你输出已加湿的单元格的个数。
思路
看题目不难发现这道题就是个网格图BFS,但是直接从每个加湿器单元格去做一变网格图BFS的话就会发现你 TLE 了,因为这么干复杂度是 \(O(n^2)\) 的,既然直接 BFS 不可行那么我们还有什么办法呢,答案是多源BFS。
多源BFS是什么:多源BFS,即同时存在多个起点,然后要求计算出图中任意一个点距离所有起点的最短距离,即图中任意点到每个起点的距离的最小值。
好了,知道了思路那么答案是啥呢?我们设一个单元格距离任意一个起点(加湿器单元格)的距离为 \(dist_{i,j}\),那么答案就是 \(dist_{i,j}\) \(\le D\) 的个数。
代码
#include <bits/stdc++.h>
#define ll long long
#define N 1001
#define mod 998244353
#define sortu(a) sort(a.begin(), a.end())
#define uniqueu(a) a.erase(unique(a.begin(), a.end()), a.end())
using namespace std;
mt19937_64 mrand(random_device{}());
const int D[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
int n, m, d;
char s[N][N];
int dist[N][N];
inline void bfs(void) {
queue<pair<int, int>> q;
memset(dist, -1, sizeof(dist));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (s[i][j] == 'H') {
dist[i][j] = 0;
q.push({i, j});
}
for ( ; !q.empty(); ) {
int x = q.front().first, y = q.front().second;
q.pop();
for (int i = 0; i < 4; i++) {
int xx = x + D[i][0], yy = y + D[i][1];
if (xx < 1 || yy < 1 || xx > n || yy > m || s[xx][yy] == '#' || dist[xx][yy] != -1)
continue;
dist[xx][yy] = dist[x][y] + 1;
q.push({xx, yy});
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &d);
for (int i = 1; i <= n; i++)
scanf("%s", s[i] + 1);
bfs();
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (dist[i][j] <= d && dist[i][j] != -1)
ans++;
printf("%d\n", ans);
}
总结
多源BFS模板题。

浙公网安备 33010602011771号