洛谷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(1≤n≤30)。

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

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

输出格式

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

朴实无华的广搜(其实深搜也行)

把边界的点全部bfs一遍,给0上色

遍历一遍,没被上色的0就是封闭的

#include<bits/stdc++.h>
using namespace std;
int sizex[5] = {0,0,-1,1};
int sizey[5] = {-1,1,0,0};
    int n;
vector<vector<int>>nums;
void bfs(int x,int y,int color){
    queue<pair<int,int>> que;
    vector<vector<bool>>used(n,vector<bool>(n,true));
    que.push(make_pair(x,y));
    while(!que.empty()){
        int x0 = que.front().first;
        int y0 = que.front().second;
        que.pop();
        for(int i = 0; i<4;i++){
            int a = x0 + sizex[i];
            int b = y0 + sizey[i];
            if(a>=n || a<0 || b >=n || b<0 || used[a][b] == false || nums[a][b] == 1){
                continue;
            }
            que.push(make_pair(a,b));
            used[a][b] = false;
            nums[a][b] = color;
        }
    }
}
int main(){
    cin >> n;
    nums.resize(n,vector<int>(n));
    for(int i = 0; i <n;i++)
    for(int j = 0; j< n;j++)
        cin >> nums[i][j];
    for(int i = 0; i <n;i++)
    for(int j = 0; j< n;j++){
        if((i == 0 || j == 0 || i == n-1 || j == n-1) && nums[i][j] == 0){
            bfs(i,j,3);
        }
    }
    for(int i = 0; i <n;i++){
    for(int j = 0; j< n;j++){
        if(nums[i][j] == 3)
        nums[i][j] = 0;
        else
        if(nums[i][j] == 0)
        nums[i][j] = 2;
        cout << nums[i][j] << ' ';
    }
        cout << endl;
    }
}

### 关于 P1162 填涂颜色的 Python 解法 P1162 的核心在于通过动态规划来解决问题。该问题可以被抽象成个二维网格上的路径计数问题,其中每步的选择受到前步状态的影响[^1]。 以下是基于动态规划的思想实个解法: #### 动态规划的状态定义 设 `dp[i][j]` 表示到达第 i 行 j 列时的不同填涂方案数量。由于每格的颜色取决于其上格和左格的颜色,因此可以通过转移方程计算当前格子的可能性数目。 #### 转移方程 对于任意位置 `(i, j)`,如果它可以从上方 `(i-1, j)` 或左侧 `(i, j-1)` 移动过来,则有如下关系: \[ dp[i][j] = (dp[i-1][j] + dp[i][j-1]) \% mod \] 这里 `%mod` 是为了防止数值过大而取模操作,通常题目会指定个较大的质数作为模数。 #### 边界条件 初始状态下,起点处只有种方式到达自己,即 \( dp[0][0] = 1 \);其他超出边界的情况均视为不可达,对应的值初始化为零。 下面是完整的 Python 实代码: ```python def fill_color(n, m, k): MOD = int(1e9 + 7) # 初始化 DP 数组 dp = [[0] * (m + 1) for _ in range(n + 1)] dp[0][0] = 1 # 枚举每个单元格并更新状态 for i in range(1, n + 1): for j in range(1, m + 1): if i == 1 and j == 1: # 特殊处理第个格子 dp[i][j] = k % MOD else: dp[i][j] = ((k - 1) * (dp[i-1][j] + dp[i][j-1])) % MOD return dp[n][m] # 输入部分 n, m, k = map(int, input().split()) result = fill_color(n, m, k) print(result) ``` 此程序实了上述逻辑,并能够高效地求解大规模输入下的结果。 --- #### 注意事项 在实际提交过程中需要注意以下几点: 1. 数据范围可能较大,需考虑优化空间复杂度。 2. 取模运算应贯穿整个过程以避免溢出错误。 3. 对于特殊情况(如单行或单列),可以直接给出结论而不必进入循环。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值