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

输出:4

#include <iostream> #include<queue> #include<cstdio> using namespace std; const int maxn=100; struct node{ int x,y; } Node; int n,m; int matrix[maxn][maxn]; bool inq[maxn][maxn]={false}; int X[4]={0,0,1,-1}; int Y[4]={1,-1,0,0}; bool judge(int x,int y) {     if(x>=n||x<0||y>=m||y<0)         return false;     if(matrix[x][y]==0||inq[x][y]==true)         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 newx=top.x+X[i];             int newy=top.y+Y[i];             if(judge(newx,newy))             {                 Node.x=newx;                 Node.y=newy;                 Q.push(Node);                 inq[newx][newy]=true;             }         }     } }
int main() {     scanf("%d%d",&n,&m);     for(int x=0;x<n;x++)     {         for(int y=0;y<m;y++)         {             scanf("%d",&matrix[x][y]);         }     }     int ans=0;     for(int x=0;x<n;x++)     {         for(int y=0;y<m;y++)         {             if(matrix[x][y]==1&&inq[x][y]==false)             {                 ans++;                 BFS(x,y);             }         }     }     printf("%d\n",ans);     return 0; }

### 如何使用 BFS 实现矩阵遍历 广度优先搜索 (BFS) 是一种用于图和树的遍历算法,其核心思想是从起始节点出发逐层扩展,直到找到目标或者完成整个图/树的遍历。在矩阵的情况下,我们可以将其视为一个二维网格图,其中每个单元格都可以看作是一个节点,而相邻的上下左右四个方向则构成该节点的邻居。 #### 据结构设计 为了实现基于 BFS矩阵遍历,通常会用到以下几种据结构: 1. **队列**:用来保存待处理的节点(即尚未完全探索过的单元格)。 2. **布尔型标记组 `visited`**:记录哪些位置已经被访问过,防止重复访问造成死循环。 3. **方向组**:定义移动的方向(上、下、左、右),便于计算当前节点的邻居坐标。 以下是具体实现方法: --- ### 示例代码 ```cpp #include <iostream> #include <queue> using namespace std; // 定义方向组,表示上下左右四种可能的移动方式 const int dx[] = {-1, 1, 0, 0}; // 行变化量 const int dy[] = {0, 0, -1, 1}; // 列变化量 void bfs(int matrix[][5], int rows, int cols) { queue<pair<int, int>> q; // 存储要访问的位置 (row, col) bool visited[rows][cols]; // 记录已访问的位置 // 初始化 visited 组为 false for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { visited[i][j] = false; } } // 假设从起点 (0, 0) 开始遍历 q.push({0, 0}); visited[0][0] = true; while (!q.empty()) { pair<int, int> current = q.front(); q.pop(); int row = current.first; int col = current.second; cout << "Visiting (" << row << ", " << col << ") with value: " << matrix[row][col] << endl; // 探索当前节点的所有邻居 for (int dir = 0; dir < 4; ++dir) { int newRow = row + dx[dir]; int newCol = col + dy[dir]; // 检查新位置是否越界以及是否已被访问 if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && !visited[newRow][newCol]) { q.push({newRow, newCol}); // 将未访问的新位置加入队列 visited[newRow][newCol] = true; // 标记为已访问 } } } } int main() { const int ROWS = 5, COLS = 5; int matrix[ROWS][COLS] = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}, {16, 17, 18, 19, 20}, {21, 22, 23, 24, 25} }; bfs(matrix, ROWS, COLS); return 0; } ``` --- ### 关键点解析 1. **初始化队列与标记组** - 使用队列来管理待访问的节点序列。 - 创建一个大小相同的布尔型组 `visited` 来跟踪已经访问过的节点,避免无限循环[^2]。 2. **方向组的作用** - 方向组简化了对当前节点周围邻居坐标的计算过程。通过简单的加减运算即可得到新的候选位置[^3]。 3. **边界条件判断** - 在尝试访问某个潜在邻居之前,必须验证它是否超出矩阵范围,并确认还未被访问过[^4]。 4. **时间复杂度分析** - 如果矩阵尺寸为 \(n \times m\) ,那么最坏情况下每个元素都会恰好进出一次队列,整体时间复杂度为 O(nm)[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值