深度优先搜索

深度优先搜索

旧街凉风 提交于 2020-02-25 20:08:16
搜索这个东西看起来简单 但实际操作时,却异常复杂 复杂就复杂在算法的优化上 深搜基操——诶 展示下吧 if判断—>for循环枚举各个方向 ->对目标操作->递归->回溯 额 优化有两种 1°:   记忆化搜索: dp题数字三角形,其中一种方法是记忆化搜索: 需要开额外空间来存储 额 就是以空间换时间 这个题就不贴代码了 2°:   剪枝: 因为剪枝比较复杂,我就举个例子说说 ROADS(算法基础与在线实践&&洛谷): 剪枝有两种  一种是可行性剪枝 及早发现正在探索的路走不到终点 因而不再走下去,这种剪枝属于比较基础的 另一种是最优性剪枝 走到某节点时发现此时付出的代价已经超过前面记录的 故不在走下去 看起来都挺简单 其实确实不复杂 但最优性剪枝的分支—— 预见性最优性剪枝 处处最优剪枝 就比较复杂了 预见性:走到某节点确实不超过范围,但预见未来必定会超过范围 故不在走下去 处处最优:记下起点到目前每一个点最优路径的代价 篇幅有限,就举例处处最优 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 struct road{ 7 int d; 8 int l; 9 int cost; 10 }; 11 vector<vector

树链剖分详解

给你一囗甜甜゛ 提交于 2020-02-22 06:44:30
  问题是这样的:对于一株树(无向无环连通图),为每个结点分配对应的权重。要求能高效计算任意两个结点之间的路径的各类信息,其中包括路径长度(路径上所有结点的权重加总),路径中最大权重,最小权重等等。到这里一切都还是比较简单的,我们可以利用Tarjan的LCA算法在线性时间复杂度内快速求解。但是如果还要求允许动态修改任意结点的权值,那么问题就不简单了。很容易发现这有些类似于线段树的问题,但是线段树是作用在区间上,而我们的问题是发生在树上的,因此线段树并不适用。而树链剖分则是可以用于求解这类问题的高效算法,其更新权值的时间复杂度为O(log2(n)),而统计路径信息的时间复杂度为O((log2(n))^2)。下面对树链剖分进行讲解。   对于任意一株树,我们记r.size表示以结点r为根的子树中的结点总数,称为r的大小。记r.next表示r的所有子结点中size属性最大的一个结点(如果没有子结点允许留空),称为r的重孩子,而其余子结点称为r的轻孩子,与重孩子相连的边称为重边,而与轻孩子相连的边称为轻边。利用深度优先搜索算法可以在O(n)时间复杂度内计算所有结点的size和next属性。   很容易发现通过将每个结点与其重孩子通过一条特殊的链条连接,那么我们就在图中建立了多条互不相交的链路,每个结点都处于一个链路中(链路可能只有一个结点),这些链路称为重链。每一条重链中所有结点深度不同

深度优先搜索

我们两清 提交于 2020-02-16 23:30:24
深度优先搜索: //深度优先搜索--数的全排列 # include <stdio.h> int a [ 10 ] , b [ 10 ] , n ; void dfs ( int step ) { int i ; if ( step == 10 ) { //说明已经有九个数字了 if ( a [ 1 ] * 100 + a [ 2 ] * 10 + a [ 3 ] + a [ 4 ] * 100 + a [ 5 ] * 10 + a [ 6 ] == a [ 7 ] * 100 + a [ 8 ] * 10 + a [ 9 ] ) { printf ( "%d%d%d+%d%d%d=%d%d%d" , a [ 1 ] , a [ 2 ] , a [ 3 ] , a [ 4 ] , a [ 5 ] , a [ 6 ] , a [ 7 ] , a [ 8 ] , a [ 9 ] ) ; total ++ ; } return ; } for ( i = 1 ; i <= n ; i ++ ) { if ( b [ i ] == 0 ) { a [ step ] = i ; b [ i ] = 1 ; dfs ( step + 1 ) ; b [ i ] = 0 ; } } return ; } int main ( ) { int total = 0 ; dfs ( 1 ) ;

栈和深度优先搜索(DFS)

被刻印的时光 ゝ 提交于 2020-02-16 11:03:14
与 BFS 类似,深度优先搜索 (DFS) 是用于在树/图中遍历/搜索的另一种重要算法。也可以在更抽象的场景中使用。 正如树的遍历中所提到的,我们可以用 DFS 进行 前序遍历 , 中序遍历 和 后序遍历 。在这三个遍历顺序中有一个共同的特性: 除非我们到达最深的结点,否则我们永远不会回溯 。 这也是 DFS 和 BFS 之间最大的区别, BFS 永远不会深入探索,除非它已经在当前层级访问了所有结点 。 模版 递归模版 有两种实现 DFS 的方法。第一种方法是进行递归: boolean DFS ( Node cur , Node target , Set < Node > visited ) { return true if cur is target ; for ( next : each neighbor of cur ) { if ( next is not in visited ) { add next to visted ; return true if DFS ( next , target , visited ) == true ; } } return false ; } 当我们递归地实现 DFS 时,似乎不需要使用任何栈。但实际上,我们使用的是由系统提供的隐式栈,也称为调用栈(Call Stack)。 显式栈模板 递归解决方案的优点是它更容易实现。 但是

树的深度优先搜索和广度优先搜索的实现

南笙酒味 提交于 2020-02-08 14:40:06
1. 深度优先 depth first search,DFS 可以使用先序遍历来实现 递归版 //先序遍历 public void PreOrder ( BinaryTreeNode node ) { if ( node != null ) { System . out . println ( node . getData ( ) ) ; //先访问根节点 PreOrder ( node . getLeftChild ( ) ) ; //先根遍历左子树 PreOrder ( node . getRightChild ( ) ) ; //先根遍历右子树 } } 非递归版(使用栈实现) public ArrayList < Integer > DfsTree ( TreeNode root ) { ArrayList < Integer > lists = new ArrayList < I > ( ) ; if ( root == null ) return lists ; Stack < TreeNode > stack = new Stack < > ( ) ; stack . push ( root ) ; while ( ! stack . isEmpty ( ) ) { TreeNode tree = stack . pop ( ) ;        //先往栈中压入右节点

bfs

六月ゝ 毕业季﹏ 提交于 2020-02-03 05:15:41
bfs原理 bfs就是广度优先搜索,与深度优先搜索有类似之处也有不同之处。 深度优先搜索是不撞南墙不回头的莽夫。 而广度优先搜索则像高塔一样稳健。 所以说广度优先搜索总是能找到一个问题的最优解,但它没有深搜那么莽夫,所以广搜所要花费的时间往往比深搜要久。 bfs的建立 bfs要先建立一个队列 struct node { int ; //至少两个,一个表示数据,一个表示数据所在的位置。 } ; 用这个结构体来表示每一步与每一步所在的位置。 区别 dfs考虑的是 当先该怎么做 并用递归写出下一次,而bfs考虑的是 下一次有几种做法 。 我这里给出dfs的文章做对比 dfs原理 例题 为了直观的显现出bfs与dfs的区别,我们用bfs来解我之前在dfs上的原题: B先生在一个迷宫里迷路了,他需要A先生的救助,A先生也不知道怎么走,所以他只能一步一步试。 现在编程来帮A先生解救B先生。 输入 m,n代表迷宫的长与宽。 m行,n列0或1.其中0代表路,1代表障碍。 出发坐标(x,y)与目标坐标(sx,sy) 输出 最短步数。 输入样例 5 4 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 4 3 输出样例 7 我们先建立一个结构体 # include <stdio.h> struct node { int x , y , s ; //x,y为坐标

数据结构之DFS与BFS实现

六眼飞鱼酱① 提交于 2020-02-03 04:41:53
本文主要包括以下内容 邻接矩阵实现无向图的BFS与DFS 邻接表实现无向图的BFS与DFS 理论介绍 深度优先搜索介绍 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似。 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 显然,深度优先搜索是一个递归的过程。 广度优先搜索介绍 广度优先搜索算法(Breadth First Search),又称为”宽度优先搜索”或”横向优先搜索”,简称BFS。 它的思想是:从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。 换句话说,广度优先搜索遍历图的过程是以v为起点,由近至远,依次访问和v有路径相通且路径长度为1,2…的顶点。 邻接矩阵实现无向图的BFS与DFS /** *

数据结构---->图的遍历

生来就可爱ヽ(ⅴ<●) 提交于 2020-02-03 04:40:52
三 图的遍历 遍历定义: 从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。 避免重复访问? 图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点。为了保证图中的各个顶点在遍历过程中访问且仅被访问一次,需要为每个顶点设一个访问标志,Vertex 类中的visited成员变量可以用来作为是否被访问过的标志。 3.1深度优先搜索( DFS )Depth First Search 深度优先搜索( depth firstsearch )遍历类似于树的先根遍历,是树的先根遍历的推广。 深度优先搜索的基本方法是:从图中某个顶点发v 出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 无向图(a)得到的遍历序列为:a , b ,c , e , f , d。 有向图(b)得到的遍历序列为:a , b ,e , c , f , d。 //对图进行深度优先遍历 public Iterator DFSTraverse(Vertex v) { LinkedList traverseSeq = new

数据结构---->图的遍历

╄→гoц情女王★ 提交于 2020-02-03 04:39:56
三 图的遍历 遍历定义: 从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。 避免重复访问? 图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点。为了保证图中的各个顶点在遍历过程中访问且仅被访问一次,需要为每个顶点设一个访问标志,Vertex 类中的visited成员变量可以用来作为是否被访问过的标志。 3.1深度优先搜索( DFS )Depth First Search 深度优先搜索( depth firstsearch )遍历类似于树的先根遍历,是树的先根遍历的推广。 深度优先搜索的基本方法是:从图中某个顶点发v 出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 无向图(a)得到的遍历序列为:a , b ,c , e , f , d。 有向图(b)得到的遍历序列为:a , b ,e , c , f , d。 //对图进行深度优先遍历 public Iterator DFSTraverse(Vertex v) { LinkedList traverseSeq = new

数据结构---->图的遍历

 ̄綄美尐妖づ 提交于 2020-02-03 04:39:05
三 图的遍历 遍历定义: 从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。 避免重复访问? 图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了曾经访问过的顶点。为了保证图中的各个顶点在遍历过程中访问且仅被访问一次,需要为每个顶点设一个访问标志,Vertex 类中的visited成员变量可以用来作为是否被访问过的标志。 3.1深度优先搜索( DFS )Depth First Search 深度优先搜索( depth firstsearch )遍历类似于树的先根遍历,是树的先根遍历的推广。 深度优先搜索的基本方法是:从图中某个顶点发v 出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。 无向图(a)得到的遍历序列为:a , b ,c , e , f , d。 有向图(b)得到的遍历序列为:a , b ,e , c , f , d。 //对图进行深度优先遍历 public Iterator DFSTraverse(Vertex v) { LinkedList traverseSeq = new