回溯 DFS 深度优先搜索[待更新]

首先申明,本文根据微博博友 @JC向北 微博日志 整理得到,本文在这转载已经受作者授权!

1.概念

回溯算法 就是 如果这个节点不满足条件 (比如说已经被访问过了),就回到上一个节点尝试别的路径

也就是说 走到死胡同里边就往回走,直到找到出口.

回溯 是一种 选优搜索 。许多复杂规模较大的问题都可以用 回溯 解决 ,因此回溯法有 “通用解题方法”的美称。

2.思想

若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。而 若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。

3.具体做法

(1)确定解空间,里边至少包含一个(最优)解。

(2)确定结点的扩展搜索规则。

(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

4.

(1)问题框架

设问题的解是一个n维向量(a1,a2,………,an),约束条件是ai(i=1,2,3,…..,n)之间满足某种条件,记为f(ai)。

(2)非递归回溯框架

   1:int a[N],i; //i 当前位置
   2: 初始化数组a[];
   3:  i=1;
   4:while(i>0(有路可走)  and  (未达到目标)) {
   5: //如果说还没找到出口,就一直找,找不到别回来见我
   6:    if(i>n)                            // 如果说1-i的节点都找到了,就出这个屋
   7:    {
   8:          搜索到一个解,输出;
   9:    }
  10:    else                                 // 处理第i个元素
  11:    {
  12:          a[i]拿第一个可能的值;
  13:          while(a[i]在不满足约束条件且在搜索空间内)
  14:          {
  15:               a[i]下一个可能的值;
  16:          }
  17:          if(a[i]在搜索空间内)
  18:         {
  19:               标识占用的资源;
  20:               i=i+1;                     // 扩展下一个结点
  21:         }
  22:         else
  23:        {
  24:              清理所占的状态空间;          // 回溯
  25:               i= i –1;
  26:         }
  27:}

1.如果说 一个屋子有多个目标点 :

总目标 = 所有目标点都找到

2.因为a[i]往下拿 拿到的节点不会重复 所以不会回到老路上去,所以只可能有一种方式出循环--找不到

3.我在这 把 JC向北 的意思转述一下:

while(i>0(还有路可走)&&没找到总目标){
if(i>n){
    //如果说 最后一条路 a[n]找到了
    保存 //如果还想找接着写条件
}else{
     a[i]取到(相对于 a[i-1]所到达的节点的)下一条路径的第一条
     while(第一条路a[i]不满足条件&&没出空间){
       a[i]取到下一条
      }
    //接下来就要判断这条路O不OK?(实际上只要判读a[i]取到的这条路O不OK)
       if(a[i]在范围内){
               OK ,i++; //去找走的通的a[i+1]
          }else{
           i--; //回溯 这个a[i]没在上一条路径的基础上找到可行的路径
             //退回去让保存上一条路径的a[i-1]试取下一个点
          }
     }
}

解决 找一个门的问题套路

while(有路可走 &&没找到){
    if(找到1条路){
        保存
       }else{
          找第一条路
       while(){
              找下一跳路
               }

     if(最后一条路满足条件){
           i++; //走下一保存资源
         }else{
              i--; //回到上一保存资源
             }
         }
}

(3)递归框架

回溯法是对解空间的深度优先搜索,在一般情况下使用递归函数来实现回溯法比较简单,其中i为搜索的深度,框架如下:

   1:int a[i];
   2:try(int i)
   3:{
   4:    if(i>n)
   5:       输出结果;
   6:     else
   7:    {
   8:       for(j= 下界; j<= 上界;j=j+1)  // 枚举i所有可能的路径
   9:       {
  10:           if(fun(j))                 // 满足限界函数和约束条件
  11:              {
  12:                 a[i]= j;
  13:               ...                         // 其他操作
 
时间: 2024-11-08 23:23:47

回溯 DFS 深度优先搜索[待更新]的相关文章

DFS(深度优先搜索)

深度优先搜索算法(Depth-First-Search),是搜索算法的一种.它沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点.这一过程一直进行到已发现从源节点可达的所有节点为止.如果还存在未被发现的节点, 则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止.DFS属于盲目搜索. 深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多

DFS 深度优先搜索例题

约翰的农场被暴风雨给淹没了,损失很大,他的保险公司将支付给他,但是支付金额取决于被淹没的最大面积.这个农场是一个边长分别为n.m的矩形,包含nm个空间,每个空间要么是干的,要么是被淹没的,一共有k个空间被淹没.求最大的淹没面积. 题目分析:首先建立坐标,标记被淹没的空间,然后从左上角搜索被淹没的空间,并取消标记,再以此为中心向四周搜索是否有被淹没的空间,有的话继续计数并取消标记,以此类推,找出所有被淹没的空间,最后排序,找到被淹没最大的面积. #include <stdio.h>#includ

算法导论——DFS深度优先搜索

package org.loda.graph; import org.loda.structure.Stack; /** * * @ClassName: DFS * @Description: 深度优先搜索(无向图) * @author minjun * @date 2015年5月24日 上午4:02:24 * */ public class DFS { //原点 private int s; // visited[i]表示i节点是否被访问过 private boolean[] visited;

GraphMatrix::DFS深度优先搜索

template <typename Tv, typename Te> //深度优先搜索DFS算法(全图) void Graph<Tv, Te>::dfs(int s) { //assert: 0 <= s < n reset(); int clock = 0; int v = s; //初始化 do //逐一检查所有顶点 if (UNDISCOVERED == status(v)) //一旦遇到尚未发现的顶点 DFS(v, clock); //即从该顶点出发启动一次D

DFS——深度优先搜索的一般格式

DFS是一种深度优先的搜索思想,运用递归完成搜索,本质上也算是穷举思想的一类,可以通过剪枝进行优化. DFS的核心是回溯和递归, 如果以迷宫为例,一般会指定走各个方向的顺序(例如先左再上再右再下).从起点开始,进入DFS(),判断是否到达终点,再判断四个方向是否可走,如果有路,DFS会进入下一格,并且进行同样的判断,此处运用了递归.当四个方向都没路时,就会回溯到上一个位置,继续判断别的方向. DFS用途十分广泛,例如在以二维数组表示的图中搜索路径,也可以用于别的方面,比如求全排列,此时将每个数字

DFS(深度优先搜索遍历有向图)-03-有向图-太平洋大西洋水流问题

给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度.“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界. 规定水流只能按照上.下.左.右四个方向流动,且只能从高到低或者在同等高度上流动. 请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标. 提示: 输出坐标的顺序不重要m 和 n 都小于150 示例: 给定下面的 5x5 矩阵: 太平洋 ~ ~ ~ ~ ~ ~ 1 2 2 3 (5) * ~ 3 2 3 (4) (4) * ~ 2

代码与算法集锦-归并排序+树状数组+快排+深度优先搜索+01背包(动态规划)

归并排序 求逆序数 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 首先考虑下如何将将二个有序数列合并.这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数.然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可. //将有序数组a[]和b[]合并到c[]中 void MemeryArray(int a[], int n, int b[], int m, int c

POJ 1979 Red and Black【深度优先搜索】

题目链接:http://poj.org/problem?id=1979 题目大意:一个矩形的房间地板被分为w*h个小块,每一个小块不是红的就是黑的,你首先站在一个黑色小块上,你只能朝你的四个方向(上下左右)移动,且不能到达红色的小块上,问你最多能到达多少个小块. 很简单的dfs深度优先搜索 没搜索过一个格子,将该格子设置为红色,之后的搜索就不会再搜索到该格子,就不会造成重复,因为该题有很多数据,记得每次处理数据是初始化各数组及其他数据. 代码如下: #include <iostream> #i

深度优先搜索(DFS)

定义: (维基百科:https://en.wikipedia.org/wiki/Depth-first_search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.是沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点.这一过程一直进行到已发现从源节点可达的所有节点为止.如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止(属于盲目搜索). 基