DFS(深度优先搜索)
定义:
深度优先搜索算法(Depth First Search,简称DFS),一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。
属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。
核心思想:
- 为了求得问题的解,先选择某一种可能情况向前探索;
- 在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;
- 如此反复进行,直至得到解或证明无解。
应用场景:
模板(主要是其模板代码的逻辑,语言的话读者自行可以让ai书写对应不同语言的模板):
int a[510]; // 存储每次选出来的数据
bool book[510]; // 标记是否被访问
int ans = 0; // 记录符合条件的次数
int n, k; // n为总数,k为选择的数量
void DFS(int cur) {
if(cur == k) { // k个数已经选完,可以进行输出等相关操作
for(int i = 0; i < cur; i++) {
cout << a[i] << " ";
}
cout << endl; // 输出结束后换行
ans++;
return;
}
for(int i = 0; i < n; i++) { // 遍历 n个数,并从中选择k个数
if(!book[i]) { // 若没有被访问
book[i] = true; // 标记已被访问
a[cur] = i; // 选定本数,并加入数组
DFS(cur + 1); // 递归,cur+1
book[i] = false; // 释放,标记为没被访问,方便下次引用
}
}
}
BFS(广度优先搜索)
定义:
广度优先搜索(Breadth-First Search,简称BFS)是一种遍历或搜索树和图的算法,也称为宽度优先搜索,BFS算法从图的某个节点开始,依次对其所有相邻节点进行探索和遍历,然后再对这些相邻节点的相邻节点进行探索,直到遍历完所有的节点。
- BFS算法使用队列来辅助实现,将起始节点放入队列中,然后依次取出队列中的节点,访问其相邻节点,并将其加入队列。这样可以保证从起始节点出发,依次按照距离顺序遍历节点。
- BFS常用于寻找最短路径,因为它按照从起点到每个节点的距离来探索节点。
核心思想:(BFS算法通常使用队列来实现)
- 创建一个队列,将起始节点加入队列;
- 创建一个集合,用于存储已经访问过的节点;
- 从队列中取出一个节点,并将其标记为已访问;
- 访问该节点的所有相邻节点,如果相邻节点未被访问,则将其加入队列;
- 重复步骤3和步骤4,直到队列为空。
应用场景:例如图的遍历、最短路径搜索等。由于BFS算法保证了按照距离顺序遍历节点,因此可以用来寻找最短路径。另外,BFS算法还可以用来判断图是否连通,即从一个节点是否可以到达另一个节点
模板(主要是其模板代码的逻辑,语言的话读者自行可以让ai书写对应不同语言的模板):
struct node {
int x, y; // 节点的坐标
};
const int MAXN = 510; // 定义一个合适的最大值
int vis[MAXN][MAXN]; // 访问标记数组
int bx[4] = {1, -1, 0, 0}; // 水平移动的方向
int by[4] = {0, 0, 1, -1}; // 垂直移动的方向
int m; // 移动方向的数量(这里为4)
void bfs(int startX, int startY) {
queue<node> q;
q.push(node{startX, startY}); // 初始化起始节点
vis[startX][startY] = 1; // 标记起始节点为已访问
while(!q.empty()) {
node tmp = q.front(); // 队首元素
q.pop(); // 出队
// 检查是否到达目标终点
if (tmp.x == targetX && tmp.y == targetY) { // 假设目标坐标为 (targetX, targetY)
// 更新逻辑,例如记录路径或其他操作
cout << "到达目标点: (" << tmp.x << ", " << tmp.y << ")\n";
return;
}
// 遍历所有可能的方向
for(int i = 0; i < m; i++) { // m个方向
int dx = tmp.x + bx[i];
int dy = tmp.y + by[i];
// 检查下标是否越界
if (dx < 0 || dx >= MAXN || dy < 0 || dy >= MAXN) {
continue; // 越界则跳过
}
// 检查是否已经被标记过
if (vis[dx][dy]) {
continue; // 已访问则跳过
}
// 否则是合法的
vis[dx][dy] = 1; // 先标记
q.push(node{dx, dy}); // 再新点入队
}
}
}
2806

被折叠的 条评论
为什么被折叠?



