P1162 填涂颜色

题目描述

由数字 0 组成的方阵中,有一任意形状的由数字 1 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 2。例如:6×6 的方阵(n=6),涂色前和涂色后的方阵如下:

如果从某个 0 出发,只向上下左右 4 个方向移动且仅经过其他 0 的情况下,无法到达方阵的边界,就认为这个 0 在闭合圈内。闭合圈不一定是环形的,可以是任意形状,但保证闭合圈内的 0 是连通的(两两之间可以相互到达)。

0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 1 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 1 2 1
1 1 1 1 1 1

输入格式

每组测试数据第一行一个整数 n(1≤n≤30)。

接下来 n 行,由 0 和 1 组成的 n×n 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 0。

输出格式

已经填好数字 2 的完整方阵。

输入输出样例

输入 #1复制

6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1

输出 #1复制

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1

说明/提示

对于 100% 的数据,1≤n≤30。

这道题可以使用深度优先搜索(DFS)或者广度优先搜索(BFS)来解决。解题的核心思路是从方阵的边界上值为 0 的点开始搜索,将所有能到达的 0 标记为一个特殊值(比如 3),这些点就是方阵外部的 0。搜索完成后,方阵中剩余的 0 就是闭合圈内的 0,将它们赋值为 2 即可。

以下是使用深度优先搜索实现的 C++ 代码:

#include 
#include 
using namespace std;

const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
int n;
vector> grid;

// 深度优先搜索函数,标记方阵外部的 0
void dfs(int x, int y) {
    if (x < 0 || x >= n || y < 0 || y >= n || grid[x][y] != 0) return;
    // 将外部的 0 标记为 3
    grid[x][y] = 3;
    for (int i = 0; i < 4; ++i) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        dfs(nx, ny);
    }
}

int main() {
    cin >> n;
    grid.resize(n, vector(n));

    // 读取方阵
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> grid[i][j];
        }
    }

    // 从方阵边界的 0 开始进行深度优先搜索
    for (int i = 0; i < n; ++i) {
        if (grid[i][0] == 0) dfs(i, 0);
        if (grid[i][n - 1] == 0) dfs(i, n - 1);
        if (grid[0][i] == 0) dfs(0, i);
        if (grid[n - 1][i] == 0) dfs(n - 1, i);
    }

    // 将剩余的 0 标记为 2
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (grid[i][j] == 0) {
                grid[i][j] = 2;
            } else if (grid[i][j] == 3) {
                // 将标记为 3 的点恢复为 0
                grid[i][j] = 0;
            }
        }
    }

    // 输出结果方阵
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cout << grid[i][j];
            if (j < n - 1) cout << " ";
        }
        cout << endl;
    }

    return 0;
}

代码解释:

  1. dfs 函数:该函数用于深度优先搜索,从边界的 0 点开始,将所有能到达的 0 标记为 3。
  2. 读取方阵:通过两层循环读取输入的方阵。
  3. 边界搜索:遍历方阵的四条边界,对边界上值为 0 的点调用 dfs 函数进行搜索。
  4. 标记闭合圈内的 0:遍历整个方阵,将值为 0 的点标记为 2,将标记为 3 的点恢复为 0。
  5. 输出结果:遍历方阵并输出结果。

复杂度分析:

  • 时间复杂度:$O(n^2)$,其中 $n$ 是方阵的边长。因为每个点最多被访问一次。
  • 空间复杂度:$O(n^2)$,主要用于存储方阵和递归调用栈。

你可能感兴趣的:(洛谷题解(限免),算法,数学建模,c++,洛谷)