BFS——洛谷P1162填涂颜色

142 篇文章 0 订阅
73 篇文章 0 订阅

题目: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;
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值