题目:https://www.luogu.org/problemnew/solution/P1162
题解
解法一:BFS
#include<bits/stdc++.h>
using namespace std;
const int M=31;
#define map mapp//避免因为使用了万能头文件而出现的重名的情况
bool vis[M][M];
int n,m,a,b,c,map[M][M];
queue <int> q;
void bfs(int x,int y){//固定格式
vis[x][y]=1;q.push(x);q.push(y);//首次进入bfs
while(!q.empty()){
int w=q.front();q.pop();
int e=q.front();q.pop();//下面是四向寻找
if(map[w+1][e]==0&&w!=n&&!vis[w+1][e]) vis[w+1][e]=1,q.push(w+1),q.push(e);
if(map[w-1][e]==0&&w!=1&&!vis[w-1][e]) vis[w-1][e]=1,q.push(w-1),q.push(e);
if(map[w][e+1]==0&&e!=n&&!vis[w][e+1]) vis[w][e+1]=1,q.push(w),q.push(e+1);
if(map[w][e-1]==0&&e!=1&&!vis[w][e-1]) vis[w][e-1]=1,q.push(w),q.push(e-1);
}
}
int main()
{//把圈外的0全部标记为1,在输出时剩下的0就是圈内的
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>map[i][j];
if(map[i][j]==1) vis[i][j]=1;//标记圈的边界
} }
for(int i=1;i<=n;i=i+n-1){//i只能是1和n,即用for循环找到左上和右上圈外的0
for(int j=1;j<=n;j++){
if(vis[i][j])continue;
bfs(i,j);//横向寻找圈外的0
}}
for(int i=1;i<=n;i=i+n-1){//i只能是1和n,即用for循环找到左下和右下圈外的0
for(int j=1;j<=n;j++){
if(vis[j][i])continue;
bfs(j,i); //纵向寻找圈外的0
}}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){if(!vis[i][j]) cout<<'2'<<' ';else cout<<map[i][j]<<' ';}
cout<<endl;
}
return 0;
}
解法二:DFS+染色
#include<bits/stdc++.h>
using namespace std;
int a[32][32];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int n,i,j;
void dfs(int p,int q)
{//将圈外的0染色成2
if(p<0||q>n+1||q<0||p>n+1||a[p][q]!=0) return;//设置返回条件,越界或该点已经走过
a[p][q]=2;//将圈外的0染色成2
for(int i=0;i<4;i++)//注意for循环的终止条件
dfs(p+dx[i],q+dy[i]);
}
int main(){
cin>>n;
for(i=1;i<=n;i++){
for(j=1;j<=n;j++) cin>>a[i][j];
}
dfs(0,0);//用dfs遍历所有圈外的0
//图形外面的一圈是0,这是一个人为设置的外连通圈,可以借助此遍历所有圈外的0,达到染色的目的
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(a[i][j]==0) cout<<'2'<<' ';
if(a[i][j]==2) cout<<'0'<<' ';
if (a[i][j]==1)cout<<'1'<<' ';
}
cout<<endl;
}
return 0;
}
解法三:先找到一个在圈内的点,然后把这个连通块染色为2
#include<bits/stdc++.h>
using namespace std;
int a[35][35];
int n,i,j,k;
bool b[5];
int main(){
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) cin>>a[i][j];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i][j]==0)
{//找到一个0 进行直接染色
for(k=1;k<=4;k++) b[k]=false;
for(k=1;k<=i;k++)if(a[k][j]==1){b[1]=true;break;}
for(k=i;k<=n;k++)if(a[k][j]==1){b[2]=true;break;}
for(k=1;k<=j;k++)if(a[i][k]==1){b[3]=true;break;}
for(k=j;k<=n;k++)if(a[i][k]==1){b[4]=true;break;}
if(b[1]&&b[2]&&b[3]&&b[4]) a[i][j]=2;
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
cout<<a[i][j]<<' ';
cout<<endl;
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int a[35][35];
int n,i,j,k;
bool b[5];
void dfs(int x,int y){//找到一个0 用dfs对圈里的连通块进行染色
a[x][y]=2;//四向搜索
if(!a[x+1][y]) dfs(x+1,y);
if(!a[x-1][y]) dfs(x-1,y);
if(!a[x][y+1]) dfs(x,y+1);
if(!a[x][y-1]) dfs(x,y-1);
}
int main(){
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) cin>>a[i][j];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i][j]==0)
{//找到一个0 用dfs对圈里的连通块进行染色
for(k=1;k<=4;k++) b[k]=false;
for(k=1;k<i;k++)if(a[k][j]==1){b[1]=true;break;}
for(k=i+1;k<=n;k++)if(a[k][j]==1){b[2]=true;break;}
for(k=1;k<j;k++)if(a[i][k]==1){b[3]=true;break;}
for(k=j+1;k<=n;k++)if(a[i][k]==1){b[4]=true;break;}
if(b[1]&&b[2]&&b[3]&&b[4]) dfs(i,j);
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)
cout<<a[i][j]<<' ';
cout<<endl;
}
return 0;
}