ACM 训练日志记录 · 思考 · 成长 提交 / 修改记录
廖夏 / 题目列表训练档案
导出

P1162 填涂颜色

来源:洛谷 ★ 1000

搜索BFSDFS连通块队列仍在学习已结束复习安排
本题活力0.29按难度、完成结果与训练证据估算

算法如山行则将至

题目描述

填涂颜色

题目描述

由数字 $0$ 组成的方阵中,有一任意形状的由数字 $1$ 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 $2$。例如:$6\times 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 \le n \le 30)$。

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

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

输出格式

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

说明/提示

对于 $100\%$ 的数据,$1 \le n \le 30$。

代码

// 初始诡异思路:路上更新->(修订)每个点都搜一遍

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN = 35;
bool mp[MAXN][MAXN];
int val[MAXN][MAXN];
bool vis[MAXN][MAXN];
int n;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int dfs(int x, int y){
    // if (vis[x][y]) return val[x][y];
    vis[x][y] = true;
    if (mp[x][y]) return 2;
    else if (x == 1 || y == 1 || x == n || y == n) return 0;
    int res = 2;
    for (int k = 0; k < 4; k++){
        int nx = x + dx[k], ny = y + dy[k];
        if (nx >= 1 && ny >= 1 && nx <= n && ny <= n && !vis[nx][ny])
            res = min(dfs(nx, ny), res);
    }
    // val[x][y] = res;
    return res; 
}
int main(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            cin >> mp[i][j];
        }
    }
    for (int i = 2; i < n; i++){
        for (int j = 2; j < n; j++){
            memset(vis, 0, sizeof(vis));
            if (!mp[i][j]){
                val[i][j] = dfs(i, j);
            }
            else if (mp[i][j]) val[i][j] = 1;
        }
    }
    for (int i = 1; i <= n; i++){
        for (int j  = 1; j <= n; j++){
            if (mp[i][j]) cout << 1;
            else cout << val[i][j];
            if (j < n) cout << " ";
        }
        cout << endl;
    }
    return 0;
}


// 标准“灌水”思路

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 35;
bool vis[MAXN][MAXN];
bool mp[MAXN][MAXN];
int n;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
void dfs(int x, int y){
    vis[x][y] = 1;
    for (int i = 0; i < 4; i++){
        int nx = x + dx[i], ny = y + dy[i];
        if (nx <= n + 1 && ny <= n + 1 && nx >= 0 && ny >= 0 && !mp[nx][ny] && !vis[nx][ny])
            dfs(nx, ny);
    }
}
int main(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            cin >> mp[i][j];
        }
    }
    dfs(0,0);
    for (int i = 1; i <= n; i++){
        for (int j  = 1; j <= n; j++){
            if (vis[i][j]) cout << 0 << " ";
            else if (mp[i][j]) cout << 1 << " ";
            else cout << 2 << " "; 
        }
        cout << endl;
    }
}