Matrix Problem(构造)

72 阅读2分钟

Matrix Problem (nowcoder.com)

原题题面

image.png

题目描述

现在给你一个 0/10/1 矩阵 CC ,要求构造两个 0/10/1 矩阵 A,BA,B ,满足在矩阵 CC 中的所有 11 均出现在 A,BA,B 中,且 A,BA,B11 的交集为 CC 中所有的 11 。同时 A,BA,B 中所有的 11 有一种联通的状态(联通:所有的 11 的上下左右四个方向至少有一个相邻的 11 。)

数据格式

image.png

输入样例

5 5
00000
00100
01010
01100
00000

输出样例

00000
00100
01110
01100
00000
00000
01110
01010
01110
00000

题目分析

这是一道 构造题

注意 CC 矩阵的最外围一圈都是 00 ,这是一个关键信息也是一个提示。

在 vp 时,我们构造了很多方式都没有成功,甚至一度尝试 dfs 进行搜素路径。

赛后看题解,发现这是一个非常巧妙的构造。其主要思想是按行或列的奇偶进行填 11,并利用相对的边界进行连结。

例如,我们将 AA 中除第一行和最后一行的其他行的所有的奇数列全部填 11 ,所有的偶数行与 CC 中一致,同时将第一行全部填 11 。将 BB 中除第一行和最后一行的其他行的所有偶数列全部填 11 ,所有的奇数行与 CC 中一致,同时将最后一行全部填 11 。可以发现这样的构造可以保证 A,BA,B 中的 11 是联通的,并且 A,BA,B11 的交集一定是 CC 中的 11 而不会产生多余的 11 ,因为在 A,BA,B 中除 CC 中的 11 之外的 11 没有重复。

Accept代码

#include <bits/stdc++.h>

using namespace std;

const int N = 510;
char c[N][N];

int main()
{
    ios::sycn_with_stdio(flase);
    cin.tie(0);
    
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) cin >> c[i] + 1;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
        {
            if (i < n && (i == 1 || j % 2 == 1 || c[i][j] == '1')) cout << 1;
            else cout << 0;
            if (j == m) cout << "\n";
        }
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
        {
            if (i > 1 && (i == n || j % 2 == 0 || c[i][j] == '1')) cout << 1;
            else cout << 0;
            if (j == m) cout << "\n";
        }
    return 0;
}