BFS识别矩阵中的块数

题目描述:
给出一个m*n的矩阵,矩阵中的元素为0或1.称位置(x,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

解题思路:对于这个问题,求解的基本思想是:枚举每一个位置的元素,如果为0,则跳过;如果为1则使用BFS查询与该位置相邻

的4个位置(前提是不出界),判断它们是否为1(如果某个位置为1,则应当继续查询与该位置相邻的4个位置,直到整个‘1’块

访问完毕)。为了防止走回头路,可以设置一个数据索引记录记录每个位置是否在BFS中已入队。

  另外,我们可以设置增量数组来表示四个方向。

(这道题目也可以使用DFS解决,具体解法参见DFS求矩阵中的连通块数

1 int x[] = {0,0,1,-1};
2 int y[] = {1,-1,0,0};

参考代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 #include <string.h>
  5 #include <ctype.h>
  6
  7 #define maxn 100
  8 #define MAX_SIZE 5    //最大队列长度+1
  9
 10
 11 struct postion{
 12     int x;
 13     int y;
 14 }pos;
 15
 16 typedef struct postion ElemType;
 17 typedef struct SqQueue{
 18     ElemType *base;    //初始化的动态分配存储空间
 19     int front;    //头指针
 20     int rear;    //尾指针,若队列不空,指向队列尾元素的下一个位置
 21 }SqQueue;
 22
 23
 24 int n,m;    //矩阵大小n*m
 25 int martix[maxn][maxn] = {0};    //01矩阵
 26 int hashflag[maxn][maxn] = {0};    //记录位置x,y是否已经入队
 27
 28 int X[] = {0,0,1,-1};
 29 int Y[] = {1,-1,0,0};
 30
 31 void BFS(int x,int y);
 32
 33 void InitQueue(SqQueue *Q);
 34
 35 int QueueEmpty(SqQueue *Q);
 36
 37 int EnQueue(SqQueue *Q,ElemType e);
 38
 39 ElemType DeQueue(SqQueue *Q);
 40
 41 int judge(int x,int y);
 42
 43 int main(){
 44
 45
 46
 47
 48     scanf("%d%d",&n,&m);        //输入矩阵大小
 49
 50     for(int x=0;x<n;x++){
 51         for(int y=0;y<m;y++){
 52             scanf("%d",&martix[x][y]);
 53         }
 54     }
 55
 56
 57
 58     int ans = 0;//统计块数
 59
 60     for(int x=0;x<n;x++){
 61         for(int y=0;y<m;y++){
 62             //如果元素为1,且未入队
 63             if(martix[x][y]==1&&hashflag[x][y]==0){
 64                 ans++;
 65                 BFS(x,y);
 66             }
 67         }
 68     }
 69
 70     printf("%d\n",ans);
 71     return 0;
 72 }
 73
 74
 75 void BFS(int x,int y){
 76     //BFS函数访问x,y所在的块,将该块中所有“1”的hashflag设置为1
 77     SqQueue Q;
 78     InitQueue(&Q);
 79
 80     pos.x = x;
 81     pos.y = y;
 82
 83     EnQueue(&Q,pos);
 84
 85     hashflag[x][y] = 1;//记录其已经入队
 86
 87     while(QueueEmpty(&Q)!=1){
 88         //printf("==============\n");
 89         ElemType top = DeQueue(&Q);    //取出队首元素,出队
 90
 91         //printf("%d %d\n",top.x,top.y);
 92         for(int i = 0;i<4;i++){    //循环四次得到四个位置
 93             int newX = top.x+X[i];
 94             int newY = top.y+Y[i];
 95             if(judge(newX,newY)){
 96                 //如果新位置需要访问
 97                 pos.x = newX;
 98                 pos.y = newY;
 99
100                 //入队
101                 EnQueue(&Q,pos);
102
103                 hashflag[newX][newY] = 1;//设置该位置已经入队了,防止走回头路
104
105             }
106         }
107     }
108 }
109
110
111 void InitQueue(SqQueue *Q){
112     //构造一个空的队列
113     (*Q).base = (ElemType*)malloc(MAX_SIZE*sizeof(ElemType));
114     if(!(*Q).base) {
115         exit(1);
116     }
117     Q->front = Q->rear = 0;
118 }
119
120 int QueueEmpty(SqQueue *Q){
121     //若队列Q为空队列,则返回1;否则返回0
122     if(Q->front == Q->rear){
123         //printf("-------------------------\n");
124         return 1;
125     }else{
126         return 0;
127     }
128 }
129
130 ElemType GetHead(SqQueue *Q){
131     //若队列Q非空,则返回队列头元素
132     if(Q->front != Q->rear){
133         return Q->base[Q->front];
134     }
135 }
136
137 int EnQueue(SqQueue *Q,ElemType e){
138     //进队元素e
139     if((Q->rear+1)%MAX_SIZE==Q->front){
140         return 0;
141     }
142     Q->base[Q->rear] = e;
143     Q->rear = (Q->rear+1)%MAX_SIZE;
144     return 1;
145
146 }
147
148
149 ElemType DeQueue(SqQueue *Q){
150     ElemType e;
151     if(Q->rear != Q->front){
152
153         e = Q->base[Q->front];
154         Q->front = (Q->front+1)%MAX_SIZE;
155         return  e;
156     }
157
158 }
159
160 int judge(int x,int y){    //判断坐标x,y是否需要访问处理
161     //如果出界,返回0,不需要进一步访问
162     if(x>=n||x<0||y>=m||y<0){
163         return 0;
164     }
165     //或者已经入队或者元素为0
166     if(martix[x][y] == 0||hashflag[x][y] == 1){
167         return 0;
168     }
169
170     return 1;
171 }

为什么代码这么长?……,主要是因为我试着实现了一下队列的常见操作,毕竟复试的OJ上能不能用STL我还不知道呢。

所以自己顺便练练。

原文地址:https://www.cnblogs.com/ManOK/p/12562601.html

时间: 2024-10-04 12:53:00

BFS识别矩阵中的块数的相关文章

LeetCode:Spiral Matrix - 螺旋输出矩阵中的元素

1.题目名称 Spiral Matrix(螺旋输出矩阵中的元素) 2.题目地址 https://leetcode.com/problems/spiral-matrix/ 3.题目内容 英文:Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. 中文:给出一个m行n列的矩阵,以螺旋顺序返回矩阵中的所有元素. 例如:现有矩阵如下: [  [ 1,

找出矩阵中含有0最多的一行(find the longest row of zero)

对于一个n*n的矩阵,其中只包含有0,1两种元素且,所有的0都在1之前,请找出矩阵中0最多的一行.(Given an N-by-N matrix of 0s and 1s such that in each row no 0 comes before a 1, find the row with the most 0s in O(N) time.) 初看这题,想到的算法就是每一行都设置一个计数器,记录每行的0的个数,然后找出最大值即可(暴力解法). 算法实现: int* find_the_lon

在如下8*6的矩阵中,请计算从A移动到B一共有____种走法。要求每次只能向上或向右移动一格,并且不能经过P。

在如下8*6的矩阵中,请计算从A移动到B一共有__种走法.要求每次只能向上或向右移动一格,并且不能经过P. A:456 B:492 C:568 D:626 E:680 F:702 解析: 8*6的矩阵,从左下角A到右上角B,一共需要走12步,其中5步向上,7步向右,因此总的走法一共有C(12,5)=792种,但题目规定不能经过P,因此需要减去经过P点的走法. 经过P的路径分为两部分,从A到P,从P到B. 同理,从A到P的走法:C(6,2)=15: 同理,从P到B的走法:C(6,3)=20: 因此

c编程:求出4&amp;#215;4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和。

//求出4×4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和 #include <stdio.h> int main() { int sum=0; int max,min; int max1,max2;//记录最大值的坐标 int min1,min2;//记录最小值的坐标 int i,j; int a[4][4]; //为数组赋值 for(i=0;i<4;i++) { for(j=0;j<4;j++) { scanf("%d",&

访问Mat矩阵中的元素并为其赋值

在OpenCV中有三种方式访问矩阵中的数据元素:容易的方式,困难的方式,以及正确的方式.今天主要讲容易方式: 最容易的方式是使用宏CV_MAT_ELEM( matrix, elemtype, row, col ),输入参数是矩阵,不是指针,网上有很多人说是指针,矩阵元素类型,行,列,返回值是相应行,列的矩阵元素.CV_MAT_ELEM可以给矩阵赋值,也可以访问矩阵元素. CV_MAT_ELEM宏实际上会调用CV_MAT_ELEM_PTR(matrix,row,col)宏来完成任务. CV_MAT

杨氏矩阵中查找元素

在杨氏矩阵中查找一个元素是否存在 杨氏矩阵即每一行均以递增顺序排列,每列从上到下也为递增顺序 方法一:数组 #include<stdio.h> #include<stdlib.h> #define COLS 3 #define ROWS 3 //要查找只要在找到右上角的元素和输入元素进行比较.如果右上角元素大,即可排除其他行,若小 //,则可排除本行,继续循环,用输入元素和右上角的元素进行比较 int find(int arr[][COLS], int rows, int cols

求一个矩阵中最大的2*2矩阵(元素和最大)的和

编程题在线编程题30分2/2最大子矩阵Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Problem Description:求一个矩阵中最大的2*2矩阵(元素和最大)的和.如:1 2 0 3 42 3 4 5 11 1 5 3 0中最大的是:4 55 3和为17输入m*n的矩阵输出该m*n矩阵的最大2*2子矩阵(元素和最大)的和 样例输入 1 2 0 3 4 ; 2 3 4 5 1 

矩阵中的路径

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子. 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子. 回溯法: public

(每日算法)LeetCode --- Word Search(矩阵中查找单词)

在矩阵中查找给定的单词是否出现,可以向上.向下.向左和向右查找.不能在一个字母上重复查找. Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically n