P1162 填涂颜色 多源BFS

解题思路

这道题要求将数字1围成的闭合圈内的所有0改为2。关键点在于如何区分闭合圈内外的0:

  1. 逆向思维:不直接找闭合圈内的0,而是找出所有与边界相连的0(这些0肯定在闭合圈外)

  2. 多源BFS:从所有边界上的0开始进行BFS,标记所有能到达的0

  3. 填色规则:

    • 未被标记的0就是闭合圈内的0,需要改为2

    • 标记过的0保持原样

    • 1保持不变

代码注释

#include<bits/stdc++.h>
using namespace std;

const int N = 3e2 + 10;  // 定义足够大的矩阵尺寸
const int inf = 0x3f3f3f3f;  // 定义无穷大值(未实际使用)

// 定义节点结构体,存储坐标
struct node {
    int x, y;  // 坐标x,y
};

int g[N][N];     // 存储原始矩阵
int vis[N][N];   // 访问标记数组,标记可以到达边界的0
int nex[4][2] = {{0,1}, {1,0}, {0,-1}, {-1,0}};  // 四个移动方向:右、下、左、上
int n;           // 矩阵大小

// BFS函数,从所有边界上的0开始搜索
void bfs(int sx, int sy) {
    queue<node> q;  // 创建队列用于BFS
    
    // 多源BFS:将所有边界上的0入队
    for(int i = 1; i <= n; i++) {
        // 上边界
        if(g[1][i] == 0) {
            vis[1][i] = 1;
            q.push({1,i});
        }
        // 下边界
        if(g[n][i] == 0) {
            vis[n][i] = 1;
            q.push({n,i});
        }
        // 左边界
        if(g[i][1] == 0) {
            vis[i][1] = 1;
            q.push({i,1});
        }
        // 右边界
        if(g[i][n] == 0) {
            vis[i][n] = 1;
            q.push({i,n});
        }
    }

    // 标准BFS过程
    while(q.size()) {
        node h = q.front(); q.pop();
        
        // 向四个方向扩展
        for(int i = 0; i < 4; i++) {
            int tx = h.x + nex[i][0];  // 新坐标x
            int ty = h.y + nex[i][1];  // 新坐标y
            
            // 边界检查
            if(tx < 1 || ty < 1 || tx > n || ty > n) continue;
            // 检查是否是1或已访问过
            if(g[tx][ty] || vis[tx][ty]) continue;
            
            vis[tx][ty] = 1;  // 标记为已访问(可以到达边界)
            q.push({tx,ty});  // 新位置入队
        }
    }
}

int main() {
    // 读取输入
    cin >> n;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            cin >> g[i][j];
    
    // 执行BFS搜索,标记所有能到达边界的0
    bfs(1, 1);
    
    // 输出结果
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(g[i][j] == 0 && vis[i][j] == 1) cout << 0 << " ";  // 能到达边界的0
            if(g[i][j] == 1) cout << 1 << " ";  // 保持1不变
            if(g[i][j] == 0 && vis[i][j] == 0) cout << 2 << " ";  // 不能到达边界的0(闭合圈内)
        }
        cout << endl;
    }
    
    return 0;
}

 

posted @ 2025-06-06 15:16  CRt0729  阅读(20)  评论(0)    收藏  举报