回溯算法和DFS联系

 

概述

回溯法是一种选优搜索法(试探法),被称为通用的解题方法,这种方法适用于解一些组合数相当大的问题。通过剪枝(约束+限界)可以大幅减少解决问题的计算量(搜索量)。

深度优先搜索(Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。
回溯和深度优先搜索的区别

回溯是一种更通用的算法。可以用于任何类型的结构,其中可以消除域的部分 ——无论它是否是逻辑树。

深度优先搜索是与搜索树或图结构相关的特定回溯形式。它使用回溯作为其使用树的方法的一部分,但仅限于树/图结构。

回溯和 DFS 之间的区别在于回溯处理隐式树而 DFS 处理显式树。这似乎微不足道,但它意味着很多。当通过回溯访问问题的搜索空间时,隐式树在其中间被遍历和修剪。然而对于 DFS 来说,它处理的树/图是明确构造的,并且在完成任何搜索之前已经抛出了不可接受的情况,即修剪掉了。

因此,回溯是隐式树的 DFS,而 DFS 是回溯而不修剪。

 回溯法的基本思想:

  1. 针对所给问题,定义问题的解空间;
  2. 确定易于搜索的解空间结构;
  3. 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

典型的解空间树

    第一类解空间树:子集树


   void Backtrack(int t){//递归层次
    if(t>n)
        Output(x);
    else{
        for(int i=0;i<=1;i++){
            x[t]=i;//记录痕迹
            if(Constraint(t)&&Bound(t))
                Backtrack(t+1);
        }
    }
   }

DFS(深度优先搜索)

  深度优先搜索基本模型

  void dfs(int step) {
        //判断边界
        //尝试每一种可能
        for (int i=1;i<=n;i++){
            //记录一些数据,例如
             sun++
            //继续下一步
            dfs(step+1);
        }
        //返回
    }

经典的DFS例题:啊哈算法的解救小哈和炸弹人(图的深度优先搜索)

//核心代码
    void dfs(int x, int y, int step) {
        int next[ 4][2]={
            {
                0, 1
            },//向右走
            {
                1, 0
            },//向下走
            {
                0, -1
            },//向左走
            {
                -1, 0
            }
        } ;//向上走
        int tx, ty, k;
        //判断是否到达小哈位置
        if (x == p && y == q) {
            if (step < min)
                min = step;
            return;
        }
        //枚举四种走法
        for (k = 0; k <= 3; k++) {
            //计算下一个点的坐标
            tx = x + next[k][0];
            ty = y + next[k][1];
            //判断是否越界
            if (tx < 1 || tx > n || ty < 1 || ty > m)
                continue;
            //判断该点是否有障碍物或者已经在路径上
            if (a[tx][ty] == 0 && book[tx][ty] == 0) {
                book[tx][ty] = 1;//标记这个点已经走过
                dfs(tx, ty, step + 1);//尝试下一个点
                book[tx][ty] = 0;//尝试结束,取消标记,恢复现场
            }
        }
        return;
    }

代码区别

子集树:x[t]=i;//记录痕迹,记录 t标记的每一层,试探每一层的所有可能

DFS图的遍历:dfs(tx, ty, step + 1);//从当前节点向下扩展,逐个试探

回溯法就是DFS+剪枝,做题时可视作同一个方法

你可能感兴趣的:(回溯算法和DFS联系)