P1162 填涂颜色 多源BFS
解题思路
这道题要求将数字1围成的闭合圈内的所有0改为2。关键点在于如何区分闭合圈内外的0:
-
逆向思维:不直接找闭合圈内的0,而是找出所有与边界相连的0(这些0肯定在闭合圈外)
-
多源BFS:从所有边界上的0开始进行BFS,标记所有能到达的0
-
填色规则:
-
未被标记的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; }

浙公网安备 33010602011771号