有这样一个题目

给出一个mxn的矩阵,矩阵中的元素为0或1,。称位置(x,y)与其上下左右四个位置(x,y+1)、(x,y-1)、(x+1,y)、(x-1,y)是相邻的。如果矩阵中有若干个1是相邻的(不必两两相邻),那么称这些1构成了一个“块”(可以理解为连通分量)。求给定的矩阵中“块”的个数。
          0 1 1 1 0 0 1
          0 0 1 0 0 0 0
          0 0 0 0 1 0 0
          0 0 0 1 1 1 0
          1 1 1 0 1 0 0
          1 1 1 1 0 0 0
例如上面的6x7矩阵中,“块”的个数是4。

对于这个问题,基本思想是枚举每一个位置的元素,如果为1且未访问过(用一个二维bool数组标记是否访问过),说明这是个新“块”,块数增1,访问该位(置对应bool二维数组元素为true),并对其进行深度搜索或者广度搜索,即同样地查询与之相邻的四个位置,枚举和遍历都结束后输出块数即可。
为方便查询相邻的四个位置,可以建立两个增量数组,表示四个方向。
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
竖着来看即(0,1)、(0,-1)、(1,0)、(-1,0)
这样就可以用for循环来枚举四个方向,以确定与当前坐标(nowX,nowY)相邻的4个位置,如下所示:

for(int i=0;i<4;i++){nowX=nowx+X[i];nowY=nowy+Y[i];}

广度遍历算法如下:

#include<cstdio>
const int maxn=100;
using namespace std;
int n,m;
int matrix[maxn][maxn];//0,1矩阵
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};//增量数组
bool inq[maxn][maxn]={false};//记录是否访问
bool judge(int x,int y){//判断坐标(x,y)是否需要访问if(x<0||x>n||y<0||y>m)//越界,返回falsereturn false;//已经访问过或当前位为0,返回falseif(inq[x][y]==true||matrix[x][y]==0)return false;//除去以上情况,返回truereturn true;
}
void dfs(int x,int y){//深度遍历算法if(!judge(x,y)) return ;//递归出口,当前位不需要访问inq[x][y]=true;//置访问位为truefor(int i=0;i<4;i++){//查询相邻的位置dfs(x+X[i],y+Y[i]);}
}
int main(){scanf("%d%d",&m,&n);//输入行列for(int i=0;i<m;i++){//输入矩阵for(int j=0;j<n;j++){scanf("%d",&matrix[i][j]);}}int ans=0;//块数for(int i=0;i<m;i++){for(int j=0;j<n;j++){//枚举每一位置if(matrix[i][j]==1&&inq[i][j]==false){//当前位为1且未访问//说明找到新"块"ans++;dfs(i,j);}}}printf("%d",ans);return 0;
}

这道题也可以用广度遍历算法来做,广度遍历算法需用到队列,枚举思想同上,如遇到为1且未访问的位,说明是新块,块数要加1,还要将这块中的所有元素都访问。广度遍历的做法是将当前位入队,访问队首元素并出队,然后将与队首相邻的需要访问的位入队,此后不断地进行出队入队操作,直到队空为止,说明本块中全部访问完了。最后输出块数。
算法只有BFS部分不同,代码如下:

#include<cstdio>
#include<queue>
const int maxn=100;
using namespace std;
int n,m;
int matrix[maxn][maxn];
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
bool inq[maxn][maxn]={false};
struct node{int x,y;
}Node;
queue<node> q;
bool judge(int x,int y){if(x<0||x>n||y<0||y>m)return false;if(inq[x][y]==true||matrix[x][y]==0)return false;return true;
}
void bfs(int x,int y){queue<node> q;//定义队列Node.x=x;Node.y=y;//为结点赋值横纵坐标q.push(Node);//将该结点入队列inq[x][y]=true;//设置该结点已经入过队while(!q.empty()){//队空即结束node top=q.front();//取队首结点q.pop();//将队首结点出队for(int i=0;i<4;i++){//访问相邻位置int nowX=top.x+X[i];int nowY=top.y+Y[i];if(judge(nowX,nowY)){//如果该位置需要访问Node.x=nowX;//设置Node坐标Node.y=nowY;q.push(Node);//将结点入队inq[Node.x][Node.y]=true;//设置该结点已入过队}}}}
int main(){scanf("%d%d",&m,&n);for(int i=0;i<m;i++){for(int j=0;j<n;j++){scanf("%d",&matrix[i][j]);}}int ans=0;for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(matrix[i][j]==1&&inq[i][j]==false){ans++;bfs(i,j);}}}printf("%d",ans);return 0;
}

最后再提醒一下,BFS中设置的inq数组的含义是判断结点是否入队,而不是是否访问过,如果含义为是否访问,考虑这种情形:当前结点已在队中,但还未访问,故inq的相应位不会置为true,此时被其他与其相邻的结点查询到,从而导致其重复入队,计算量大增。
还有一点就是STL的 queue的push操作只是制造了一个该元素的一个副本入队,因此在入队后对原元素的访问不会影响队中的副本,对队中副本的修改也不会改变原元素,这点和传递指针是相反的。

求矩阵的连通分支数问题相关推荐

  1. 牛客-计算机复试题-求图的连通分支数

    求图的连通分支数可以用并查集实现. 并查集的讲解推荐: https://blog.csdn.net/liujian20150808/article/details/50848646 本题求的是无向图的 ...

  2. DFS求图的连通分支、割点数、判断是否连通

    连通分支数 /*DFS求图的连通分支数 */ #include <stdio.h> #define N 1 //看是否所有顶点都被访问标记过 int IsVisit(int visit[] ...

  3. 无向图的连通分支数(并查集)

    目录 这是牛客网上题号为 KY268 的一道题 题目描述:该题的目的是要你统计图的连通分支数. 输入描述:每个输入文件包含若干行,每行两个整数 i, j,表示节点 i 和 j 之间存在一条边. 输出描 ...

  4. C语言求矩阵的逆(伴随法)

    之前介绍了C语言用代数余子式求行列式 本次开始介绍如何用公式法对矩阵求逆,并用C语言将其实现. 之前程序有点小bug,已于2022年11月29日修改. 目录 数学原理 矩阵求逆的公式 数乘矩阵 程序设 ...

  5. 2013吉林通化邀请赛 1004 D-City 并查集求连通分支数

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4496 将题目要查询的数倒过来求,先加一条边,保存cc(连通分支数)  然后再加一条边.... 当合并两 ...

  6. 首先从键盘上两个矩阵的行数n和列数m,然后输入两个矩阵A和B的元素值,最后求出两个矩阵的和C并输出其元素值。

    输入格式: 第1行包含两个整数n和m,表示矩阵的行数和列数. 接下来n行,每行m个整数,表示矩阵A的元素值. 再接下来n行,每行m个整数,表示矩阵B的元素值. 相邻两个整数之间用空格分隔. 输出格式: ...

  7. matlab求矩阵均值向量,如何求一个矩阵的均值向量

    四.线性方程组 考试内容 线性方程组的克莱姆(Cramer)法则 线性方程组有解和无解的判定齐次线性方程组的基础解系和通解非齐次线性方程组的解与相应的齐次线性方程组(导出组)的解之间的关系非齐次线性方 ...

  8. HDU 4587 TWO NODES(割两个点的最大连通分支数)

    http://acm.hdu.edu.cn/showproblem.php?pid=4587 题意: 给一图,求割去两个点后所能形成的最大连通分支数. 思路: 对于这种情况,第一个只能枚举,然后在删除 ...

  9. Java黑皮书课后题第8章:*8.1(求矩阵中各列数字的和)使用下面的方法头编写一个方法,求矩阵中特定列的所有元素的和。编写一个测试程序,读取3*4矩阵,显示每列元素的和

    *8.1(求矩阵中各列数字的和)使用下面的方法头编写一个方法,求矩阵中特定列的所有元素的和.编写一个测试程序,读取3*4矩阵,显示每列元素的和 题目 题目描述与运行示例 破题 代码 题目 题目描述与运 ...

最新文章

  1. python绘制柱形图-Python openpyxl Excel绘制柱形图
  2. 在新浪潮中,服务教育是你的竞争利器
  3. android sha1是签名么,Android获取SHA1和MD5签名
  4. 删除文件夹下面n天前时间的文件
  5. 夺命雷公狗---PDO NO:13 PDO的预处理查询4
  6. 关于BIO和NIO的理解
  7. 苹果投影仪_无线投屏才是真正的王道,明基智能商务投影仪E580
  8. get/post在线接口
  9. 分词统计(四)唐宋元诗人吟诗作词的时候,最偏爱哪些词语呢?(附上AI写的1000句诗!)
  10. [羊城杯 2020]Easyphp2
  11. 基于STM32C8T6的MLX90614-DCC红外无线测温系统
  12. oracle rap,部署RAP服务器
  13. hihoCoder1378 (最大流最小割)
  14. 华硕FL5900U笔记本电脑重装win10专业版详细操作教程
  15. 钢铁侠材质制作——3、基础光照模型实现
  16. 使用火焰图(FlameGraph)分析程序性能
  17. 【第48题】实现一个冒泡排序
  18. discuz3.4安装php,Discuz!X3.4论坛源码下载 及 全新安装教程
  19. Swi-Prolog借助XPCE可视化-显示图片
  20. 安装Markdownpad2后出现的错误(This view has crashed)解决

热门文章

  1. 数美科技CEO唐会军受聘中国信通院互联网新技术新业务安全评估中心高级评估专家
  2. 有道桌面词典老是显示网络已断开的解决方案
  3. [Python] replace函数
  4. 2023年东北大学计算机科学与技术考研上岸前辈初复试备考经验指导
  5. 从实验室走向生活,亚略特推动AI商业价值落地
  6. 取出切词后词频高的词
  7. php常用函数讲解,php常用函数处理的函数解析
  8. 写代码是人命关天的工作:盘点那些改变世界的代码 ,程序员惊了
  9. 向日葵远程黑屏无效问题解决--最新
  10. 正态分布概率表_如何用Excel计算一个投资组合的回报率达到预定目标的概率?...