2026.06.01 作业 - # AT_abc460_d [ABC460D] Repeatedly Repainting
题目描述
有一个 \(H\) 行 \(W\) 列的网格,其中第 \(i\) 行第 \(j\) 列的单元格被称为单元格 \((i,j)\)。
所有单元格都被涂上了黑白两种颜色,网格被描述为 \(H\) 个长度为 \(W\) 的字符串 \(S_1,S_2,...,S_H\)。如果 \(S_i\) 的第 \(j\) 个字符为 .,则单元格 \((i,j)\) 为白色;如果 \(S_i\) 的第 \(j\) 个字符为 #,则单元格 \((i,j)\) 为黑色。
你需要执行 \(10^{100}\) 次操作。
-
规则同时适用于所有单元格。
- 对于一个白色的单元格,当且仅当它相邻的单元格中有一个是黑色,它就会变成黑色。这里的“相邻”指的是一个单元格 \((x^\prime,y^\prime)\) 在另一个单元格 \((x,y)\) 的 \(8\) -邻域上,也就是说,\(\max(|x-x^\prime|,|y-y^\prime|)=1\)。
- 对于一个黑色的单元格,它会变成白色。
求操作后所有单元格的颜色情况。
输入格式
输入以如下格式给出。
\(H\) \(W\) \(S_1\) \(S_2\) \(...\) \(S_H\)
输出格式
输出 \(H\) 行,每行一个长度为 \(W\) 的字符串,由 . 和 # 组成,表示 \(10^{100}\) 次操作后网格的颜色情况。
如果单元格 \((i,j)\) 为白色则在第 \(i\) 行第 \(j\) 列输出 .,如果为黑色则在第 \(i\) 行第 \(j\) 列输出 #。
输入输出样例 #1
输入 #1
3 4
#.#.
.#..
#...
输出 #1
#.#.
.#..
#..#
输入输出样例 #2
输入 #2
3 3
###
###
###
输出 #2
...
...
...
输入输出样例 #3
输入 #3
5 7
.#.....
.......
..#....
.......
....#..
输出 #3
.#.##.#
....#..
#.#.###
#.....#
###.#.#
说明/提示
数据范围
- \(1\leq H\times W\leq10^6\)
- \(H\) 和 \(W\) 为正整数。
- \(S_i\) 为长度为 \(W\) 的字符串,由
.和#构成。
题解
给出 \(H\) 行 \(W\) 列网格,#代表黑格、.代表白格。
重复无限次如下操作(交替翻转变色):
- 白→黑:白色格子,8相邻有至少1个黑格 → 变成黑色;否则保持白色。
- 黑→白:所有黑色格子直接变成白色。
思考
- 情况1: 如果所有的格子的周边都有不同颜色的格子,该网格就会出现黑白交替变换。
- 情况2:全部是黑色,全部是白色,最终都是白色。
- 情况3: 除了情况2,最终都会转化为情况1。
问题就转换为,什么时候出现周围有其他颜色的格子,就是出现黑白交替的时候。
即可算出任何一个格子经过无穷的偶数次转换后的颜色。
关键规律
-
用BFS求每个白格子到最近初始
#的最短步数,白色格子一旦被染色后,就会出现黑白交替。 -
需要特殊预处理: -
#周围都是#,该格子的距离值不为0,当且仅当该格子被再次染色为黑色,才会黑白交替的颜色变换。 -
样例1
5 5
#....
.....
.....
.....
.....

C++ BFS完整AC代码(洛谷AT_abc460_d)
#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;
const int INF = 1e9;
// 完美的 8 方向数组
const int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int H, W;
if (!(cin >> H >> W)) return 0;
vector<string> a(H);
for (int i = 0; i < H; i++) {
cin >> a[i];
}
// 1. 找出满足黑白交替性质的‘#’ 。
// ‘# ’周边有 '.' ,才能视为距离值为 0 的点。
vector<string> b(H, string(W, '.'));
bool has_black = false;
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (a[i][j] == '#') {
for (int d = 0; d < 8; d++) {
int tx = i + dx[d];
int ty = j + dy[d];
if (tx >= 0 && tx < H && ty >= 0 && ty < W) {
if (a[tx][ty] == '.') {
b[tx][ty] = '#';
has_black = true; //存在可以传播颜色的黑色点。
}
}
}
}
}
}
// 情况2: 全 # 或 全 .,那后面永远都是全白
if (!has_black) {
for (int i = 0; i < H; i++) {
cout << string(W, '.') << '\n';
}
return 0;
}
//BFS 初始化
vector<vector<int>> dis(H, vector<int>(W, INF));
queue<pair<int, int>> q;
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (b[i][j] == '#') {
dis[i][j] = 0;
q.push({i, j});
}
}
}
// 将情况3转换为情况1。
while (!q.empty()) {
auto [x, y] = q.front(); q.pop();
for (int d = 0; d < 8; d++) {
int tx = x + dx[d];
int ty = y + dy[d];
if (tx >= 0 && tx < H && ty >= 0 && ty < W) {
if (dis[tx][ty] == INF) {
dis[tx][ty] = dis[x][y] + 1;
q.push({tx, ty});
}
}
}
}
//第一次变成黑色的奇偶性质,决定最后的颜色。
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (dis[i][j] % 2 != 0) {
cout << '#';
} else {
cout << '.';
}
}
cout << '\n';
}
return 0;
}

浙公网安备 33010602011771号