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\) 列网格,#代表黑格、.代表白格。
重复无限次如下操作(交替翻转变色):

  1. 白→黑:白色格子,8相邻有至少1个黑格 → 变成黑色;否则保持白色。
  2. 黑→白:所有黑色格子直接变成白色。

思考

  • 情况1: 如果所有的格子的周边都有不同颜色的格子,该网格就会出现黑白交替变换。
  • 情况2:全部是黑色,全部是白色,最终都是白色。
  • 情况3: 除了情况2,最终都会转化为情况1。

问题就转换为,什么时候出现周围有其他颜色的格子,就是出现黑白交替的时候。
即可算出任何一个格子经过无穷的偶数次转换后的颜色。

关键规律

  • 用BFS求每个白格子到最近初始#的最短步数,白色格子一旦被染色后,就会出现黑白交替。

  • 需要特殊预处理: - # 周围都是 #,该格子的距离值不为 0 ,当且仅当该格子被再次染色为黑色,才会黑白交替的颜色变换。

  • 样例1

5 5
#....
.....
.....
.....
.....

bfs1

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;
}
posted @ 2026-06-03 18:18  alice_ss  阅读(17)  评论(0)    收藏  举报
//雪花飘落效果