简要题意:
给定一个 \(n \times m\) 的字符矩阵 \(p\),仅由 .
(表示未涂色) 和 #
(表示涂色) 构成。保证边界无色。
要求构造出两个 \(n \times m\) 的字符矩阵(也由 .
和 #
构成)\(a,b\),满足 \(a\) 和 \(b\) 均涂色的部分恰为 \(p\),且均为一个连通块。
\(n,m \leq 500\).(可强化至 \(n,m \leq 5 \times 10^3\).)
典型构造题,以样例 \(n = 5\) 为例:
注意到 边界无色 这个条件。所以我们可以考虑一种从边界出发的染色方式。
即先把 \(a,b\) 染成这样:
####.
#....
####.
#....
####.
....#
.####
....#
.####
....#
注意到,下面对于每一个,出现在 \(p\) 中而未出现在 \(a,b\) 中的格子,直接染即可。因为一定是一个连通块。
时间复杂度:\(\mathcal{O}(nm)\).
#include <bits/stdc++.h>
using namespace std;
const int N = 5e2 + 1;
int n, m;
char a[N][N], b[N][N];
int main() {
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
if(i % 2 == 1 && j < m || i % 2 == 0 && j == 1) a[i][j] = '#';
else a[i][j] = '.';
if(i % 2 == 0 && j > 1 || i % 2 == 1 && j == m) b[i][j] = '#';
else b[i][j] = '.';
}
char s[N];
for(int i = 1; i <= n; i++) {
scanf("%s",s);
for(int j = 0 ; j < m; j++)
if(s[j] == '#') a[i][j + 1] = b[i][j + 1] = '#';
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) putchar(a[i][j]);
puts("");
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) putchar(b[i][j]);
puts("");
}
}