想必在学习过程中,bfs和dfs的思路和代码一直难以理解,给出具体的思路和代码供大家参考:
通过洪水问题进行求解BFS和DFS
BFS
1.算法思路
-
用队列进行储存,用头队列对四个方向进行扩散,头出尾进入
-
每一次扩散呈涟漪式,最外一圈
2.具体代码
#include <bits/stdc++.h> // 导入所有标准库
using namespace std;
int n, m, f[1001][1001], ans; // 定义n, m, 二维数组f和答案ans
char a[1001][1001]; // 定义字符矩阵a
// 定义节点结构体
struct node {
int x, y; // 节点的坐标
};
queue<node> q; // 定义节点队列
// 定义四个方向的移动数组,分别表示上下左右
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
// 广度优先搜索算法
void bfs(int x, int y) {
q.push({x, y}); // 将初始节点入队
a[x][y] = '0'; // 标记访问过的节点为'0'
while (!q.empty()) { // 当队列不为空时循环
node t = q.front(); // 取队首元素
q.pop(); // 弹出队首元素
for (int i = 0; i < 4; i++) { // 遍历四个方向
int xx = t.x + dx[i], yy = t.y + dy[i]; // 计算新的坐标
// 判断新的坐标是否在边界内并且未被访问过
if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && a[xx][yy] != '0') {
q.push({xx, yy}); // 将新节点入队
a[xx][yy] = '0'; // 标记访问过的节点为'0'
}
}
}
}
int main() {
cin >> n >> m; // 输入矩阵的行数和列数
memset(a, '0', sizeof(a)); // 初始化矩阵a为'0'
for (int i = 1; i <= n; i++) // 遍历输入矩阵的每一行
for (int j = 1; j <= m; j++) // 遍历输入矩阵的每一列
cin >> a[i][j]; // 输入矩阵的每个元素
for (int i = 1; i <= n; i++) // 遍历矩阵的每一行
for (int j = 1; j <= m; j++) // 遍历矩阵的每一列
if (a[i][j] != '0') { // 如果当前元素未被访问过
ans++; // 计数答案
bfs(i, j); // 进行广度优先搜索
}
cout << ans; // 输出答案
return 0; // 返回0,表示程序结束
}
DFS
1.算法思路
-
传入坐标x和y
-
注意边界控制,x和y都要在合理的边界范围内,如果走过该点,就将其标记为0
-
按顺序进行下 上 右 左 四个方向去递归遍历
-
当进行回溯时发现走不通,就会一层一层往上退出来
2.具体代码
#include <bits/stdc++.h> // 包含所有标准库头文件,加快开发速度,但实际使用时应只包含需要的头文件
using namespace std;
// 声明全局变量
int n, m; // 分别表示矩阵的行数和列数
int f[1001][1001]; // 辅助矩阵(未使用,但保留了变量名)
int ans; // 记录结果,即连通区域的数量
char a[1001][1001]; // 字符矩阵,用于表示输入的地图
// 深度优先搜索(DFS)函数,用于标记访问过的区域
void dfs(int x, int y) {
// 判断坐标是否越界或当前位置是否为'0',如果是则返回
if (x < 1 || x > n || y < 1 || y > m || a[x][y] == '0') return;
// 将当前坐标标记为已访问
a[x][y] = '0';
// 递归地访问上下左右四个方向的相邻节点
dfs(x + 1, y); // 向下
dfs(x - 1, y); // 向上
dfs(x, y + 1); // 向右
dfs(x, y - 1); // 向左
}
int main() {
// 输入矩阵的行数和列数
cin >> n >> m;
// 初始化字符矩阵a,将所有元素初始化为'0'
memset(a, '0', sizeof(a));
// 输入矩阵的实际内容,从第1行第1列开始
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
}
}
// 遍历矩阵的每个元素,找出所有不为'@'的连通区域
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (a[i][j] != '0') { // 如果当前元素不是'0'
ans++; // 计数器加一,表示发现一个新的连通区域
dfs(i, j); // 对该区域进行DFS,将其标记为已访问
}
}
}
// 输出结果,即连通区域的数量
cout << ans;
return 0;
}