最大联通(蓝桥杯题)
01矩阵中点数最大的连通块点数
思路如下:我们用for循环遍历01矩阵,当遍历到1时,标记该点(表示已经搜过了),让color-=1(color是用来染色的,表示这是哪个连通块),
然后进入dfs(x,y,color)。dfs的作用是搜索与当前这个点(x,y)相邻的点(上下左右)。
dfs的实现在代码中解释
其中最关键的就是color的取法,取好了能简化很多代码。
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{
cout << 148;
}
(bushi
实现代码如下:(DFS)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int a[30+2][60+2];//存地图
int num;//用来染色的
int cnt[32*62];//存连通块中1的点数
bool col[32][62];//标记该点有没有搜过
void dfs(int x,int y,int color)
{
//之间对该个连通块++,说明该点在该连通块中
cnt[-color]++;//为什么color要取负,请先看主函数中color是如何取值的
a[y][x] = color;
//方向变量
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
//对上下左右每个点都搜一遍(类似bfs)
for(int i = 0;i<4;i++)
{
int tx = x + dx[i];
int ty = y + dy[i];
if(tx>=1&&tx<=60&&ty>=1&&ty<=30)
{
if(a[ty][tx]>0&&col[ty][tx]==0)
{
//标记该店已经搜过了,否则在下一个dfs中会搜回来
col[ty][tx] = 1;
dfs(tx,ty,color);//继续搜tx,ty上下左右的点
}
}
}
}
int main()
{
string s;
for(int i = 1;i<=30;i++)
{
cin >> s;//之间cin >> a[i][j]的话不能达到存地图的目的,会将第一行的01当作一个数输入进a[1][1]。
for(int j = 1;j <= 60;j++)
{
a[i][j] = s[j-1] - '0';
}
}
int mmax = 0;//用来保存最大的连通块点数
for(int i = 1;i<=30;i++)
for(int j = 1;j<=60;j++)
if(a[i][j]>0)//如果找到了1(这就是体现color取值的好处的地方,因为num--,所以染色一定会染成负数,只有1是>0的,所以只需要一个判断,就能找出没被搜过的1)
{
num--;//每找到一个新的连通块,就--得到新的染色值,由于是负数,所以dfs中color要取负
col[i][j] = 1;//标记,表示搜过了
dfs(j,i,num);//彻底搜索该点所在的连通块
mmax = max(mmax,cnt[-num]);//找最大的连通块点数
}
cout << mmax;//输出点数,同理,如果想知道01矩阵中连通块数量的话,只需要输出-num即可。
}
01矩阵中连通块数量
其实上面的代码也可以实现求01矩阵中连通块的数量,但是上面代码用的是dfs,这里我使用bfs实现
思路与上面代码相似,
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int a[30+2][60+2];
int num;//用来染色的
int cnt[32*62];
bool col[32][62];
PII q[32*62];
void bfs(int x,int y,int color)
{
cnt[-color]++;//点数+1
a[y][x] = color;//染色
int hh = 0,tt = -1;//数组模拟队列
q[++tt] = {x,y};//存当前的点
//方向变量
int dx[4] = {0,0,1,-1};
int dy[4] = {-1,1,0,0};
while(hh<=tt)//遍历队列
{
//col[ty][tx] = 1;//不能在这里表示搜过了,由于bfs是宽度优先搜索,在这里标记的话会多搜很多次!!!
auto t = q[hh++];
//搜4个方向
for(int i = 0;i<4;i++)
{
int tx = t.first + dx[i];
int ty = t.second + dy[i];
//满足条件
if(tx>=1&&tx<=60&&ty>=1&&ty<=30)
if(col[ty][tx]==0&&a[ty][tx]>0)
{
//则存点
q[++tt] = {tx,ty};
//连通块点数+1
cnt[-color]++;
//给该点染色
a[ty][tx] = color;
//一定要在这里表示该点搜过了!!!
col[ty][tx] = 1;//这里很重要!!!
}
}
}
}
int main()
{
string s;
for(int i = 1;i<=30;i++)
{
cin >> s;
for(int j = 1;j <= 60;j++)
{
a[i][j] = s[j-1] - '0';
}
}
int mmax = 0;
for(int i = 1;i<=30;i++)
for(int j = 1;j<=60;j++)
if(a[i][j]>0)
{
num--;
col[i][j] = 1;
bfs(j,i,num);
mmax = max(mmax,cnt[-num]);
}
cout << -num;//连通块数量
//for(int i = 1;i<=-num;i++)cout << cnt[i] << '\n';//这是我debug的语句·-·
}
❀完结撒花❀