填涂颜色
题目描述
由数字 $0$ 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 $1$ 构成,围圈时只走上下左右 $4$ 个方向。现要求把闭合圈内的所有空间都填写成 $2$。例如:$6\times 6$ 的方阵($n=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
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
输入格式
每组测试数据第一行一个整数 $n(1 \le n \le 30)$。
接下来 $n$ 行,由 $0$ 和 $1$ 组成的 $n \times n$ 的方阵。
方阵内只有一个闭合圈,圈内至少有一个 $0$。
//感谢黄小U饮品指出本题数据和数据格式不一样. 已修改(输入格式)
输出格式
已经填好数字 $2$ 的完整方阵。
样例 #1
样例输入 #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 \le n \le 30$。
思路分析
很难直接找出被1包围住的区域内的点,因此转而找没有被围住的点。很容易发现只有与边缘点相连通的点是没有被围住的,因此以边缘上的0为起点bfs搜索一遍并标记,剩下没有被搜索过的0就应该被改为2。
代码
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
int map[40][40],dx[4]={1,-1,0,0},dy[4]={0,0,1,-1},n;
bool gone[40][40];
struct Point{
int x,y;
};
void bfs(int x,int y){
queue<Point> q;
q.push({x,y});
gone[x][y]=true;
while(!q.empty()){
int xn=q.front().x,yn=q.front().y;
q.pop();
for(int i=0;i<4;i++){
int x1=xn+dx[i],y1=yn+dy[i];
if(x1>=1&&x1<=n&&y1<=n&&y1>=1&&map[x1][y1]==0&&!gone[x1][y1]){
q.push({x1,y1});
gone[x1][y1]=true;
}
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cin>>map[i][j];
for(int i=1;i<=n;i++){
if(!map[1][i]&&!gone[1][i]) bfs(1,i);
else if(!map[n][i]&&!gone[n][i]) bfs(n,i);
else if(!map[i][1]&&!gone[i][1]) bfs(i,1);
else if(!map[i][n]&&!gone[i][n]) bfs(i,n);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(map[i][j]==0){
if(gone[i][j]) cout<<"0 ";
else cout<<"2 ";
}
else cout<<"1 ";
}
cout<<endl;
}
return 0;
}