- 第 163 篇 -
Date: 2026 - 02- 08 (周日)
Author: 郑龙浩(仟墨)
2026-02-08 周日 | 算法打卡day3
文章目录
-
- [2026-02-08 周日 | 算法打卡day3](#2026-02-08 周日 | 算法打卡day3)
3_卡码网99_计数孤岛_DFS
使用BFS
题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。
后续 N 行,每行包含 M 个数字,数字为 1 或者 0。
输出描述
输出一个整数,表示岛屿的数量。如果不存在岛屿,则输出 0。
输入示例
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例
3
cpp
// Date: 2026-02-08 Author:郑龙浩
// 3_卡码99_计数孤岛_BFS.cpp
// BFS
// 用时:
#include "bits/stdc++.h"
using namespace std;
int direction[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
// 技巧:只要加入队列,就立刻标记(代表走过) + 先给(x, y)当前位置标记,再给周围的位置标记
// 队列在广度优先搜索中发挥着核心作用。由于队列遵循先进先出的原则,它能确保算法按照层级顺序遍历图中的节点。具体来说,
// 算法会从起始节点开始,将其加入队列并标记为已访问。在遍历过程中,每当从队列前端取出一个节点进行处理时,
// 会立即将该节点的所有未访问且符合条件的相邻节点加入队列末尾。这种机制保证了先被发现的节点会先被处理,
// 从而使搜索范围从起点开始逐层均匀向外扩展,首先处理距离为1的直接邻居,接着处理距离为2的节点,
// 依此类推,最终实现了按层级遍历的效果,这正是广度优先搜索"广度"二字的体现。
void bfs(vector <vector <int>>& grid, vector <vector <bool>>& visited, int x, int y) {
int heigth = grid.size();
int width = grid[0].size();
queue <pair <int, int>> que;
que.push({x, y}); // 先将当前坐标放入que中去
visited[x][y] = true; // 标记当前
int curX, curY, nextX, nextY;
while (!que.empty()) {
// 取出队列中的岛屿坐标
curX = que.front().first;
curY = que.front().second;
que.pop(); // 取出岛屿后弹出
for (int i = 0; i < 4; i++) {
nextX = curX + direction[i][0];
nextY = curY + direction[i][1];
if (nextX >=0 && nextX < heigth && nextY >= 0 && nextY < width && grid[nextX][nextY] == 1 && visited[nextX][nextY] == false) {
que.push({nextX, nextY}); // 将下一个坐标加入que
visited[nextX][nextY] = true;
}
}
}
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int N, M, cnt= 0;
cin >> N >> M;
vector <vector <int>> grid(N, vector <int>(M, 0));
vector <vector <bool>> visited(N, vector <bool>(M, false));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> grid[i][j];
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (grid[i][j] == 1 && visited[i][j] == 0) { // 如果(i, j)位置是陆地且没有访问过,则找到了新的岛屿,cnt++ 且 使用BFS广搜附近所有与(i, j)连接的岛屿,如果找到了,就用visited标记下
cnt++;
bfs(grid, visited, i, j);
}
}
}
cout << cnt;
return 0;
}
4_卡码网100_最大岛屿的面积
**题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,计算岛屿的最大面积。岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。后续 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出一个整数,表示岛屿的最大面积。如果不存在岛屿,则输出 0。
输入示例
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例
4
cpp
// Date: 2026-02-08 Author:郑龙浩
// 4_卡码网100_最大岛屿的面积
// 方法1:DFS
// 用时:
#include "bits/stdc++.h"
using namespace std;
int direction[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int S = 0; // 每个小岛面积
void dfs(vector <vector <int>>& grid, vector <vector <bool>>& visited, int x, int y) {
int width = grid[0].size();
int height = grid.size();
visited[x][y] = true;
S++;
for (int i = 0; i < 4; i++) {
int nextX = x + direction[i][0];
int nextY = y + direction[i][1];
if (nextX >= 0 && nextX < height && nextY >= 0 && nextY < width && grid[nextX][nextY] == 1 && visited[nextX][nextY] == false) {
dfs(grid, visited, nextX, nextY);
}
}
return; // 可写可不写
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int N, M, max = 0;
cin >> N >> M;
vector <vector <int>> grid(N, vector <int>(M, 0));
vector <vector <bool>> visited(N, vector <bool>(M, false));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> grid[i][j];
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j ++) {
if (grid[i][j] == 1 && visited[i][j] == false) {
S = 0; // 每次发现新的岛屿,都要将面积重置为0
dfs(grid, visited, i, j);
if (max < S) max = S;
}
}
}
cout << max;
return 0;
}