- 第 162 篇 -
Date: 2026 - 02- 07
Author: 郑龙浩(仟墨)
2026-02-07 周五 | 算法打卡day2
文章目录
-
- [2026-02-07 周五 | 算法打卡day2](#2026-02-07 周五 | 算法打卡day2)
3_卡码网99_计数孤岛_DFS
算法: DFS
题目描述
给定一个由 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-07 Author:郑龙浩
// 3_卡码99_计数孤岛_DFS.cpp
// DFS
// 用时: 60min
#include "bits/stdc++.h"
using namespace std;
int direction[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
// 写法1:显性终止条件(先判断坐标是否合理,后标记,再dfs搜索下一个坐标)
void dfs1(vector <vector <int>>& grid, vector <vector <bool>>& visited, int x, int y) {
int height = grid.size(); // 高
int width = grid[0].size(); // 宽
if (x < 0 || x > height - 1 || y < 0 || y > width - 1) return; // 如果越界,终止
if (grid[x][y] == 0 || visited[x][y] == true) return; // 如果当前坐标 是海洋,或者访问过,终止
visited[x][y] = true; // 将当前坐标标记为 已访问过
// 只检查周围四个坐标点
int nextX, nextY;
for (int i = 0; i < 4; i ++) {
nextX = x + direction[i][0];
nextY = y + direction[i][1];
dfs1(grid, visited, nextX, nextY); // 意思:用dfs深搜遍历 (nextX, nextY) 周围的四个点
}
}
// 写法2:隐性终止条件(先标记,后面检查坐标,如果不合条件,是不会执行下一次的标记的,所以前面可以在不检查的条件下进行标记的操作)
void dfs2(vector <vector <int>>& grid, vector <vector <bool>>& visited, int x, int y) {
int height = grid.size(); // 高
int width = grid[0].size(); // 宽
visited[x][y] = true; // 将当前坐标标记为 已访问过
// 只检查周围四个坐标点
int nextX, nextY;
for (int i = 0; i < 4; i ++) {
nextX = x + direction[i][0];
nextY = y + direction[i][1];
if (nextX < height && nextX >= 0 && nextY < width && nextY >= 0 && grid[nextX][nextY] == 1 && visited[nextX][nextY] == false) { // 如果下一个坐标没有越界且是陆地,且没有访问过,就用dfs深搜遍历它周围四个点
dfs2(grid, visited, nextX, nextY);
}
}
}
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) {
dfs2(grid, visited, i, j); // 通过DFS标记这个岛屿的所有相连陆地
cnt ++; // 岛屿数量加1
}
}
}
cout << cnt;
return 0;
}