DFS/BFS

  • 深度搜索(DFS)
    • 深度搜索思路:`回溯 + 剪枝`
    • 基本思路
    • 深度搜索模板
    • 深度搜索经典例题:【排列数字】
    • 深度搜索经典例题:【n-皇后问题】
  • 广度搜索(BFS)
    • 深度搜索简介
    • 基本思路
    • 深度搜索经典例题:【走迷宫——边的权值相同】

深度搜索(DFS)

深度搜索思路:回溯 + 剪枝

深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次.

举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束).简要说明深度优先搜索的特点:每次深度优先搜索的结果必然是图的一个连通分量.深度优先搜索可以从多点发起.如果将每个节点在深度优先搜索过程中的"结束时间"排序(具体做法是创建一个list,然后在每个节点的相邻节点都已被访问的情况下,将该节点加入list结尾,然后逆转整个链表),则我们可以得到所谓的"拓扑排序",即topological
sort.

基本思路

深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。 当然,当人们刚刚掌握深度优先搜索的时候常常用它来走迷宫.事实上我们还有别的方法,那就是广度优先搜索(BFS).

(1)对于下面的树而言,DFS方法首先从根节点1开始,其搜索节点顺序是1,2,3,4,5,6,7,8(假定左分枝和右分枝中优先选择左分枝)。

(2)从stack中访问栈顶的点;

(3)找出与此点邻接的且尚未遍历的点,进行标记,然后放入stack中,依次进行;

(4)如果此点没有尚未遍历的邻接点,则将此点从stack中弹出,再按照(3)依次进行;


(5)直到遍历完整个树,stack里的元素都将弹出,最后栈为空,DFS遍历完成。


深度搜索模板

int check(参数)
{if(满足条件)return 1;return 0;
}void dfs(int step)
{判断边界if{到达边界时的操作(输出等)}未到边界时尝试每一种可能else{满足check条件 if{标记继续下一步 : dfs(step+1)恢复初始状态}};
}

深度搜索经典例题:【排列数字】

原题链接

给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

输入格式
共一行,包含一个整数 n。

输出格式
按字典序输出所有排列方案,每个方案占一行。

数据范围
1≤n≤71≤n≤71≤n≤7
输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

题目答案:

#include<bits/stdc++.h>using namespace std;
int path[N];
bool vis[N];
int n;
void dfs(int x){if(x > n){for (int i = 1; i <= n; ++i) cout<<path[i]<<" ";puts("");return;}else{for (int i = 1; i <= n; ++i) {if(!vis[i]){path[x] = i;vis[i] = true;dfs(x+1);vis[i] = false;}}}
}int main() {cin>>n;dfs(1);return 0;
}

深度搜索经典例题:【n-皇后问题】

原题链接
n−皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。


现在给定整数 n,请你输出所有的满足条件的棋子摆法。

输入格式
共一行,包含整数 n。

输出格式
每个解决方案占 n 行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。每个方案输出完成后,输出一个空行。注意:行末不能有多余空格。输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围
1≤n≤91≤n≤91≤n≤9
输入样例:

4

输出样例:

.Q..
...Q
Q...
..Q...Q.
Q...
...Q
.Q..

(DFS按行枚举) 时间复杂度 O(n!)O(n!)O(n!)
代码分析

对角线 dg[u+i]dg[u+i]dg[u+i],反对角线udg[n−u+i]udg[n−u+i]udg[n−u+i]中的下标 u+iu+iu+i和 n−u+in−u+in−u+i 表示的是截距

下面分析中的 (x,y)(x,y)(x,y) 相当于上面的 (u,i)(u,i)(u,i)
反对角线 y=x+by=x+by=x+b, 截距 b=y−xb=y−xb=y−x,因为我们要把 b 当做数组下标来用,显然 b 不能是负的,所以我们加上 +n(实际上+n+4,+2n都行),来保证是结果是正的,即 y−x+ny - x + ny−x+n
而对角线 y=−x+by=−x+by=−x+b, 截距是 b=y+xb=y+xb=y+x,这里截距一定是正的,所以不需要加偏移量
核心目的:找一些合法的下标来表示 dgdgdg 或 udgudgudg 是否被标记过,所以如果你愿意,你取 udg[n+n−u+i]udg[n+n−u+i]udg[n+n−u+i] 也可以,只要所有 (u,i)(u,i)(u,i) 对可以映射过去就行

题目答案:

#include<bits/stdc++.h>using namespace std;
const int N = 100;
char g[N][N];  // g[N][N]用来存路径
// bool数组用来判断搜索的下一个位置是否可行
bool col[N],dg[N],udg[N]; // g[N][N]用来存路径
int n;void dfs(int x){// u == n 表示已经搜了n行,故输出这条路径if(x == n){for (int i = 0; i < n; ++i) puts(g[i]); // 等价于cout << g[i] << endl;puts(""); // 换行return;}else{for (int i = 0; i < n; ++i) {// 剪枝(对于不满足要求的点,不再继续往下搜索)// udg[n - u + i],+n是为了保证下标非负if(!col[i] && !dg[x+i] && !udg[n-x+i]){g[x][i] = 'Q';col[i] = dg[x+i] = udg[n-x+i] = true;dfs(x+1);g[x][i] = '.';col[i] = dg[x+i] = udg[n-x+i] = false;// 恢复现场 这步很关键}}}}
int main() {cin>>n;for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {g[i][j] = '.';}}dfs(0);return 0;
}

广度搜索(BFS)

深度搜索简介

广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历算法这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。基本过程,BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。一般用队列数据结构来辅助实现BFS算法。

基本思路

(1)给出一连通图,如图,初始化全是白色(未访问);

(2)搜索起点V1(灰色);

(3)已搜索V1(黑色),即将搜索V2,V3,V4(标灰);

(4)对V2,V3,V4重复以上操作;

(5)直到终点V7被染灰,终止;

(6)最短路径为V1,V4,V7.

深度搜索经典例题:【走迷宫——边的权值相同】

给定一个 n∗mn*mn∗m 的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0 表示可以走的路,1 表示不可通过的墙壁。
最初,有一个人位于左上角 (1,1)(1, 1)(1,1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 (n,m)(n, m)(n,m) 处,至少需要移动多少次。
据保证 (1,1)(1, 1)(1,1) 处和 (n,m)(n, m)(n,m) 处的数字为 0,且一定至少存在一条通路。

输入格式

第一行包含两个整数n和m。
接下来n行,每行包含m个整数(0或1),表示完整的二维数组迷宫。

输出格式

输出一个整数,表示从左上角移动至右下角的最少移动次数。

数据范围

1≤n,m≤1001≤n,m≤1001≤n,m≤100

输入样例:

5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出样例:

8

答案解析:

#include<bits/stdc++.h>using namespace std;
const int N = 110;
int n,m;
int g[N][N],d[N][N];  // g记录迷宫,d记录该位置与起始位置的距离
typedef pair<int,int> PII;
queue<PII> q;int bfs(){int dx[] = {-1,0,1,0},dy[] = {0,1,0,-1};q.push({0,0}); //从第一个元素开始访问d[0][0] = 0;while(!q.empty()){auto t = q.front();  q.pop();for(int i = 0;i < 4;i++){int x = t.first+dx[i] , y = t.second+dy[i];if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && !d[x][y]){d[x][y] = d[t.first][t.second]+1;q.push({x,y});}}}return d[n-1][m-1];
}int main() {cin>>n>>m;for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin>>g[i][j];cout<<bfs()<<endl;return 0;
}

深度搜索(DFS) 和 广度搜索(BFS)相关推荐

  1. 【算法】深度搜索(DFS) 和 广度搜索(BFS)

    深度搜索(DFS) 点:然后退回到该顶点,搜索其它路径,直到以该顶点为始点的所有路径的顶点都被访问,深度搜索算法是递归算法,因为对于没一个节点来说,执行的是同样的操作.  简单来说,深度搜素算法就是一 ...

  2. 深度搜索(DFS)和广度搜索(BFS)

    深度搜索(DFS) 一.搜索方法:  沿出发顶点的第一条路径尽量深入,遍历路径上所有顶点:然后退回到该顶点,搜索其它路径,直到以该顶点为始点的所有路径的顶点都被访问,深度搜索算法是递归算法,因为对于没 ...

  3. 一文搞定深度优先搜索(DFS)与广度优先搜索(BFS)【含完整源码】

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  4. 【蓝桥杯】2015决赛A组 5 穿越雷区(深度优先搜索dfs、广度优先搜索bfs)

    历届试题 穿越雷区 问题描述 X星的坦克战车很奇怪,它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转,否则将报废. 某坦克需要从A区到B区去(A,B区本身是安全区,没有正能量或负能量特征), ...

  5. 【数据结构与算法】2.深度优先搜索DFS、广度优先搜索BFS

    原文链接:https://blog.csdn.net/qq_41681241/article/details/81432634 总结 一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的 ...

  6. 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法

    深度优先(DFS) 深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接 ...

  7. 深度优先搜索(DFS)和广度优先搜索(BFS)探究

    附BFS解题代码: #include<iostream> #include<queue> using namespace std;char room[23][23]; int ...

  8. 深度搜索(DFS),一种用于遍历和搜索的算法

    先上百度对深度搜索的定义: 如果上边的定义没有理解,那么可以这样认为:深度搜索就是一种试探性的算法,例如你在一个十字路口想要去到某地,但是你又不认识具体的路(并且你不善言辞,万事不求人),那么你只能先 ...

  9. 万能的搜索——深度搜索和广度搜索

    搜索分为深度优先搜索(dfs)和广度优先搜索(bfs) 深度搜索和广度搜索的区别是: 深度搜索是往深度方向进行搜索的,先选一条路走到底,再选另一条路: 广度搜索是一层一层的,把一层上的所有情况都搜索到 ...

  10. 数据结构与算法—图论之dfs、bfs(深度优先搜索、宽度优先搜索)

    文章目录 前言 邻接矩阵和邻接表 深度优先搜索(dfs) 宽度(广度)优先搜索(bfs) 总结与比较 前言 在有向图和无向图中,如果节点之间无权值或者权值相等,那么dfs和bfs时常出现在日常算法中. ...

最新文章

  1. b站弹幕 xml php 乱码,B站弹幕Python爬行XML响应中的代码转换问题,python,之,取,b,xml,时,转码...
  2. 数据库锁机制为什么很重要?
  3. 浮点数能进行取模运算吗?(不行,暂时只能是两个整数之间)
  4. 计算机常考应用分析题,计算机常见故障及排除
  5. Vue.js Class 与 Style 绑定
  6. npm 安装yarn_问题解决记录-npm和yarn全局安装成功后命令无法执行的问题
  7. boost::adjacency_list用法的测试程序
  8. 用计算机和用纸的区别,英语四级机考与传统纸考的主要区别
  9. java容器类添加元素失败失败_java容器 Set
  10. mysql数据库任务驱动式教程课后答案_MySQL数据库任务驱动式教程
  11. 2017.02.19学习C#的第二天,今天我学到了什么?
  12. adobe flash player android 4.4,adobe flash player最新版
  13. LTE学习笔记之接口协议
  14. 输电线缺陷检测 计算机工程与设计,小波去噪和混沌理论应用于输电线缺陷检测-计算机工程与应用.pdf...
  15. Android 左飞字幕的实现(带描边)
  16. IDEA之Translation翻译插件-TKK: 更新 TKK 失败
  17. canvas教程13-使用图片
  18. 正则匹配---匹配包含指定字符串
  19. SassPassIass
  20. Zion医疗中心使用RTLS系统,减少气垫丢失概率

热门文章

  1. 利用LSB算法隐藏图片信息的MATLAB实现
  2. 科三——应对特殊情况
  3. Mysql基本知识1
  4. 集体心智:社会网络拓扑塑造集体认知
  5. android 控制手机,如何用Android手机控制另一部手机[详细说明]
  6. java base64图片计算图片大小
  7. ISLR读书笔记十六:最大边际分类器(maximal margin classifier)
  8. Win7 远程桌面限制IP
  9. 【社招】量化研究员(机器学习)-Akuna Capital -上海
  10. C++关键字(static/register/atuo/extern/volatile/const/inline/define/typedef)