本文已收录于专栏 ⭐️ 《算法通关笔记》⭐️

算法模版:暴力搜索之DFS

  • 前言
  • 基本概念
  • 算法思想
  • 常用模板
  • 三种枚举方式
    • 指数型枚举
    • 排列型枚举
    • 组合型枚举
  • 完结散花
  • 题目练习
  • 参考文章

前言

唤我沈七就行。
今天带来的是骗分神器–DFS

基本概念

DFS:是Depth First Search的简称 ,即深度优先搜索算法
是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。

DFS是通过递归来实现的,也就是函数自己调用自己。
所以通俗的说DFS通过递归枚举所有情况,然后从中找到与题设相符的方案。
因为要枚举所以情况属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。
所以DFS不算是最有效率的算法,但一定是考虑情况最全面的算法。

算法思想

回溯法是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。
但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
回溯是DFS最精妙的一步,在算法模板中往往体现在恢复现场
即在调用完函数自身后,恢复初始状态。
这是因为DFS要枚举所有情况,而枚举方式不是想BFS那样一层一层的,而是一条路走到尾,他每走一步都需要在走的路上做上标记,防止重复走同一条路。
如果没路了,再通过回溯,走下条路。而回溯在这里的作用就是按原路返回,但是因为路上已经做了标记,所以回溯其实就是撤销上一步做的标记(恢复现场)。不然是没办法返回走下一条路的。

如果不理解的没关系,我当初学的时候也是懵懵懂懂,先接着往下看~

常用模板


void dfs(int step)
{判断边界//判断是否符合条件{相应操作}枚举每一种可能{标记 //防止多次重复枚举同一个方案继续下一步dfs(step+1)恢复初始状态(回溯的时候要用到)//恢复现场//这就是DFS的精髓之处//为的就是不影响下一种方案的枚举}
}

三种枚举方式

DFS通常有三种枚举方式,接下来我们一一来介绍

指数型枚举

从 1∼n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案

分析: 从1~n依次考虑 选 和 不选 两种情况。 一共 n 个数,每个数有 2 种情况。总共方案数为 2的n次方。所以被称为指数型枚举。

详细的解释都在注释里

const int N = 1e1 + 6; 定义一个常量N
int n;
int st[N];  记录每个位置当前的状态:0表示还没考虑,1表示选它,2表示不选它void dfs(int u)  枚举的第几个数字
{if(u > n) {  终止条件,因为题目要求一个就n个数 所以只有 u>n 就输出枚举的方案for(int i = 1; i <= n; i++)if(st[i] == 1) printf("%d ", i);puts("");return;}st[u] = 1;   选它的分支dfs(u + 1);st[u] = 0;   恢复现场,以便进行下一个分支st[u] = 2;   不选它的分支dfs(u + 1);st[u] = 0;   恢复现场
}
int main(void)
{scanf("%d", &n);dfs(1);return 0;
}

排列型枚举

把 1∼n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。

分析:依次枚举 1~n数 放到哪个位置,排列问题需要考虑顺序,需要book数组来判重。

const int N = 10;
int st[N]; 存储方案
bool book[N]; 标记数字是否被用过,true表示被用过,false表示没被用过
定义在里全局变量,所以现在book数组都是false 表示都没被用过
int n;
void dfs(int u){ 当前枚举第u位if(u > n){for(int i = 1; i <= n; i ++) printf("%d ", st[i]); 打印方案puts("");return ;}for(int i = 1; i <= n; i ++){ 依次枚举每个数if(!book[i]) 如果当前数没被用过{        st[u] = i;       在第u位是ibook[i] = true;  标记用过dfs(u + 1);  递归到下一位恢复现场,以便回溯其他情况st[u] = 0;  可省略 因为写不写都会被 st[u]=i; 这一层给覆盖掉book[i] = false;  不可省 }}
}
int main(){scanf("%d", &n);dfs(1);return 0;
}

组合型枚举

从 1∼n 这 n 个整数中随机选出 m 个,按字典序输出所有可能的选择方案。

组合问题和排列问题不同,不需要考虑顺序,即 1234 和 4321 都是一种组合.
因为要按字典序输出,所以需要从上一次枚举的数开始来依次枚举,控制局部枚举的数,使得新枚举的数比之前的大。
组合问题不需要考虑顺序,需要x来记录上一次的枚举的数。这样也就可以保证同一种组合只有一种顺序被打印。
因为是从上一次枚举的数开始枚举所以不会保存选用重复数字, 所以不需要定义去重数组book。

int n,m;
int cnt[30]; 记录方案
void dfs(int u,int x){  u 记录枚举了几位 x记录了枚举了到了几if(u>m) {  边界for(int i=1;i<=n;i++)cout<<cnt[i]<<" ";puts("");  换行return;}for(int i=x;i<=n;i++) 从x开始枚举{cnt[u]=i;dfs(u+1,i+1);cnt[u]=0; 恢复现场 }
}
int main()
{cin>>n>>m;dfs(1,1);return 0;
}

完结散花

ok以上就是对 暴力搜索之DFS 的全部讲解啦,很感谢你能看到这儿啦。如果有遗漏、错误或者有更加通俗易懂的讲解,欢迎小伙伴私信我,我后期再补充完善。

题目练习

检验知识是否学会当然是不断刷题啦,下面我给出一部分DFS相关的一些经典题目。
后续如果我有时间就更新这部分知识的题解,到时候就可以配套学习啦。
N皇后
八皇后
全排列问题

参考文章

参考文献
https://blog.csdn.net/weixin_43272781/article/details

算法模版:暴力搜索之DFS【沈七】相关推荐

  1. 高级数据结构与算法 | 深度遍历搜索(DFS)与广度遍历搜索(BFS)

    文章目录 深度优先搜索(DFS) 员工的重要性 图像渲染 岛屿的周长 被围绕的区域 岛屿数量 岛屿的最大面积 广度优先搜索(BFS) N叉树的层序遍历 腐烂的橘子 单词接龙 最小基因变化 打开转盘锁 ...

  2. C++ 暴力搜索String pattern search字符串模式的实现算法(附完整源码)

    C++暴力搜索String pattern search字符串模式的实现算法 C++暴力搜索String pattern search字符串模式的实现算法完整源码(定义,实现,main函数测试) C+ ...

  3. 算法模版:模拟数据结构之绪论【沈七】

    算法模版:模拟数据结构之绪论 前言 什么是数据结构? 先看数据 再看结构 一些术语 逻辑结构 储存结构 完结散花 参考文献 前言 唤我沈七就好. 算下来应该是有两周没更新了. 是因为最近一直在研究数据 ...

  4. 算法模板:动态规划之01背包【沈七】

    算法模板:动态规划之01背包 前言 动态规划 01背包 二维背包 一维优化 经典习题 小A点菜 5 倍经验日 买干草 完结散花 参考文献 前言 唤我沈七就好啦. 动态规划 核心作用:优化 当数据范围& ...

  5. 算法模板:归并排序【沈七】

    本文已收录于专栏 ⭐️ <算法通关笔记>⭐️ 算法模版:归并排序 前言 基本概念 算法思想 常用模板 完结散花 参考文献 前言 唤我沈七就好. 往期专栏: 算法模板:快速排序 基本概念 归 ...

  6. “暴力美学1”——DFS深度优先搜索

    作为新时代青年,"暴力"二字似乎离我们十分遥远,大多数时候我们只能够在电影或者电视剧上接触这个概念 暴力二字或许是个贬义词,但若是我们在后面加上美学二字,或许就是一个值得推敲的词汇 ...

  7. Java实现算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)

    对算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)用Java实现其中的伪代码算法,案例也采用算法导论中的图. import java.util.ArrayList; import java ...

  8. 深度优先搜索(DFS)与广度优先搜索(BFS)算法详解

    深度优先搜索(DFS)与广度优先搜索(BFS)详解 1.广度优先搜索算法 1.1.前言 和树的遍历类似,图的遍历也是从图中某点出发,然后按照某种方法对图中所有顶点进行访问,且仅访问一次. 但是图的遍历 ...

  9. 算法模板:动态规划之线性DP【沈七】

    算法模板:动态规划之线性DP 前言 线性DP 数字三角形模型 摘花生 最小路径和 不同路径模型 不同路径(有障碍) 过河卒 (综合应用) 最长上升子序列模型 木棍加工 导弹拦截 完结散花 参考文献 前 ...

最新文章

  1. CSS选择器笔记,element element和element element 的区别
  2. 【Rain in ACStar HDU-3340】
  3. acid(数据库事务正确执行的四个基本要素的缩写)
  4. Qt笔记-进程只能存在1个(Linux适用,Windows有思路)
  5. verilog学习记(快速入门)
  6. 《qos》一书受到读者好评
  7. 素性测试AKS算法程序
  8. 智慧医院建设方案_【聚焦医改】安泰创新智慧医院建设方案惊艳中国医院院长大会!...
  9. ssl教程易语言代码
  10. 教育学相关期刊杂志介绍
  11. TCP 之 抓包分析
  12. 单循环赛制php,告别东西部分组LPL实行常规赛单循环赛制
  13. centos7无法上网问题
  14. JAVA面试算法小记
  15. 手机短号码(mobile)C++
  16. FlexRay在AUTOSAR的实施
  17. 主页改index.php,如何更改首页默认index.php改成index.html
  18. vscode 快速生层vue模板
  19. redhat linux中文,Redhat 中文解决方案
  20. lua --- 基本语法学习

热门文章

  1. yolov3运行及保存检测视频(包括摄像头)
  2. 大货跟踪程序精简版v1.20200731
  3. 工作日计算问题思路和实现
  4. 怎么把一张普通照片变成一寸照?这个小技巧了解一下
  5. 将CSS文件转换为标准格式
  6. 华为手机如何实现语音转文字?简单的很,一步步教你完成
  7. shell——命令排序
  8. Project Treble是Android升级的最终方案吗?
  9. 装逼利器:QQ号转换成16进制登陆--用了这么长时间QQ竟然不知道
  10. MATLAB 3D极坐标绘图