题目
思路
又是我们的老朋友,连通块类问题,我们依旧用dfs求解。
建立这样的思路:dfs搜索,当遇到0时就染色为1,也即将图染色成这样:具体方法见上一篇文章:dfs模板例
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
话不多说,先上代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int nums[53][53];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void dfs(int x,int y){
if(x<0||y<0||x>n+1||y>n+1||nums[x][y]==1)return;
nums[x][y]=1;
for(int i=0;i<4;i++){
int newx=x+dx[i];
int newy=y+dy[i];
dfs(newx,newy);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>nums[i][j];
nums_copy[i][j]=nums[i][j];
}
}
dfs(0,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(nums[i][j]==0)
nums[i][j]=2;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<nums[i][j]<<" ";
}
cout<<"\n";
}
}
结果就是:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
好像与题意不符捏......
题目让我们只将包围的连通块染色,那么我们可以这样:建立一个nums的副本,将原始输入的nums拷贝,染色后我们再拿来对比,只要副本对应位置为0,而染色后的对应位置为1,说明该位置是被标记染色过的,这时我们再重新染回来,反过来,如果副本和染色后的位置均为0,说明这个位置是dfs没有搜到的地方,也就是被包围的地方,我们不做处理就行。
#include<bits/stdc++.h>
using namespace std;
int n;
int nums[53][53];
int nums_copy[53][53];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void dfs(int x,int y){
if(x<0||y<0||x>n+1||y>n+1||nums[x][y]==1)return;
nums[x][y]=1;
for(int i=0;i<4;i++){
int newx=x+dx[i];
int newy=y+dy[i];
dfs(newx,newy);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>nums[i][j];
nums_copy[i][j]=nums[i][j];
}
}
dfs(0,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(nums[i][j]==0)
nums[i][j]=2;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(nums_copy[i][j]==0&&nums[i][j]==1){
nums[i][j]=0;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<nums[i][j]<<" ";
}
cout<<"\n";
}
}