DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了

您所在的位置:网站首页 折痕题怎么解 DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了

DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了

2024-07-13 10:01:05| 来源: 网络整理| 查看: 265

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

一、基本思想 为了求得问题的解,先选择某一种可能情况向前探索;在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;如此反复进行,直至得到解或证明无解。 二、操作步骤: 初始原点为v0,使用深度优先搜索,首先访问 v0 -> v1 -> v2 -> v5,到 v5 后面没有结点,则回溯到 v1 ,即最近的且连接有没访问结点的结点v1;此次从 v1 出发,访问 v1 -> v4 -> v6 -> v3,此时与v3相连的两个结点 v0 与 v6 都已经访问过,回溯到 v6 (v6 具有没访问过的结点);此次从 v6 出发,访问 v6 -> v7,到 v7 后面没有结点,回溯;一直回溯到源点 v0 ,没有没访问过的结点,程序结束。

注:下面图中箭头为回溯方向 在这里插入图片描述

三、模板

C模板:

int a[510]; //存储每次选出来的数据 int book[510]; //标记是否被访问 int ans = 0; //记录符合条件的次数 void DFS(int cur){ if(cur == k){ //k个数已经选完,可以进行输出等相关操作 for(int i = 0; i //遍历 n个数,并从中选择k个数 if(!book[i]){ //若没有被访问 book[i] = 1; //标记已被访问 a[cur] = i; //选定本数,并加入数组 DFS(cur + 1); //递归,cur+1 book[i] = 0; //释放,标记为没被访问,方便下次引用 } } }

C++模板:

vector a; // 记录每次排列 vector book; //标记是否被访问 void DFS(int cur, int k, vector& nums){ if(cur == k){ //k个数已经选完,可以进行输出等相关操作 for(int i = 0; i //遍历 n个数,并从中选择k个数 if(book[nums[i]] == 0){ //若没有被访问 a.push_back(nums[i]); //选定本输,并加入数组 book[nums[i]] = 1; //标记已被访问 DFS(cur + 1, n, nums); //递归,cur+1 book[nums[i]] = 0; //释放,标记为没被访问,方便下次引用 a.pop_back(); //弹出刚刚标记为未访问的数 } } } 四、例题

学算法当然要刷题领悟啦,不然就是我这种一看就会(只是背了下来),一写就废的菜鸡 ^ - ^ 下面就让我们一起看看这个俗称不撞南墙不回头算法都有哪些例题!!!

1、排列问题 题目一:

设有n个整数的集合{1,2,…,n},从中取出任意r个数进行排列(1 //已经去够r个数 for(int i = 0; i //循环遍历保证不漏 if(!book[i]){ //若没访问过 book[i] = 1; //标记已访问 a[cur] = i; //i符合条件加入 DFS(cur + 1); //寻找一个数字 book[i] = 0; //回溯:清除标记 } } } int main(){ cin >> n >> r; DFS(0); cout ans.push_back(a); return ; } for(int i = 0; i a.push_back(nums[i]); book[nums[i]] = 1; DFS(cur + 1, n, nums); book[nums[i]] = 0; a.pop_back(); } } } vector permute(vector& nums) { int n = nums.size(); DFS(0, n, nums); return ans; } 题目三:

【LeetCode每日一题】784. 字母大小写全排列 —— DFS算法(C/C++)

给定一个字符串 s ,通过将字符串 s 中的每个字母转变大小写,我们可以获得一个新的字符串。

返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。

示例 1:

输入:s = “a1b2” 输出:[“a1b2”, “a1B2”, “A1b2”, “A1B2”]

示例 2:

输入: s = “3z4” 输出: [“3z4”,“3Z4”]

提示: 1 ans.push_back(s); return ; } if(isdigit(s[cur])){ DFS(cur + 1, s); }else{ s[cur] = tolower(s[cur]); DFS(cur + 1, s); s[cur] = toupper(s[cur]); DFS(cur + 1, s); } } vector letterCasePermutation(string s) { DFS(0, s); return ans; } 2、组合问题 题目一:

【LeetCode每日一题】77. 组合 —— DFS算法(C/C++) 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 :

输入:n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]

提示: 1 a.push_back(b); return ; } for(int i = 1; i //第一个数或者后面的数大于前面的数 b.push_back(i); //符合加入 DFS(cur + 1, n, k); //递归选择下一个数 b.pop_back(); //弹出 } } } vector combine(int n, int k) { DFS(0, n, k); return a; } 3、n皇后问题 题目一:

洛谷——P1219 [USACO1.5]八皇后 Checker Challenge 一个如下的 6 * 6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

在这里插入图片描述

上面的布局可以用序列 2 4 6 1 3 5 来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 6 列号 2 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。 并把它们以上面的序列方法输出,解按字典顺序排列。 请输出前 33 个解。最后一行是解的总个数。

输入格式:

一行一个正整数 n,表示棋盘是 n×n 大小的。

输出格式:

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

示例:

输入:6 输出: 2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4

分析:

问题的关键在于如何判定某个皇后所在的行、列、斜线上是否有别的皇后;可以从矩阵的特点上找到规律,如果在同一行,则行号相同;如果在同一列上,则列号相同;如果同在/斜线上的行列值之和相同;如果同在\斜线上的行列值之差相同;从下图可验证:

在摆放皇后时,可以”按行摆放”(这样就保证了皇后不会横向攻击)。即:

(1)起点为 dfs(0),即从第0行开始摆放皇后,逐行进行。同时使用一维数组 map 保存第 cur 行的皇后摆放的列,也就是说每次尝试摆放皇后的位置坐标为 (cur, map[cur]);

(2)逐列遍历,若发现位置 (i, map[j]) 与位置 (cur, map[cur]) 在同一列 或 同一主对角线 或 同一副对角线上时,摆放失败,该方案”作废”,继续执行;

(3)若摆放成功,则 dfs(cur+1),表示继续摆放下一行,过程同上;

(4)当 cur=n,即n行皇后均摆放完成时,表示该方案可行,总方案数+1。

AC代码: #include using namespace std; const int M = 20; int ans = 0, n; int a[M]; //标记i行 纵坐标为a[i] void dfs(int cur){ int flag = 1; //标记该序列是否可行 if(cur == n){ if(ans cout if(a[cur] == a[j] || cur+a[cur] == j+a[j] || cur-a[cur] == j-a[j]){ flag = 0; break; } } if(flag == 1){ dfs(cur+1); } } } int main(){ cin >> n; dfs(0); cout if(x % i == 0) return false; } return true; } void dfs(int cur, int sum, int t){ if(cur == k){ if(Judge(sum)) cnt++; return; } for(int i = t; i fill(book, book + 30, 0); cin >> n >> k; for(int i = 0; i


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭