zoukankan      html  css  js  c++  java
  • 回溯、递归、DFS方法

    转自:https://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html1.

    1.回溯解法框架

    我觉得这个递归方法更好理解,迭代的方法我没太看懂。

       1: int a[n];
       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:               ...                         // 其他操作
      14:                 try(i+1);
      15:               回溯前的清理工作(如a[i]置空值等);
      16:               }
      17:          }
      18:      }
      19: }

    以非常典型的,leetcode22题,生成括号为例:

    class Solution(object):
        def generateParenthesis(self, N):
            ans = []
            def backtrack(S = '', left = 0, right = 0):
                if len(S) == 2 * N: #给出解空间
                    ans.append(S)
                    return
                if left < N:#这两个if判断都是剪枝
                    backtrack(S+'(', left+1, right) #扩展搜索节点
                if right < left:#这里是关键
                    backtrack(S+')', left, right+1)
    
            backtrack()
            return ans

        (1)针对所给问题,确定问题的解空间:

                首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。 (对应if判断解)

        (2)确定结点的扩展搜索规则    (确定往下搜索调用)

        (3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。(if判断递归调用条件)

    https://leetcode.com/articles/letter-combinations-of-a-phone-number/ 就像这道题,它只是一个简单的深度优先遍历然后得到所有的解,我觉得它关键是没有剪枝和回去的过程,只是遍历到最深的节点,然后返回了。

    2.DFS和回溯的关系

    https://www.1point3acres.com/bbs/thread-137584-1-1.html这个讲的挺好的。

    特点:就是recursive call之后要退回到之前的一个状态。

    回溯是DFS的一种,是它的子集。

    回溯不保留树结构,也就是剪枝的意思。 

    定义:https://stackoverflow.com/questions/1294720/whats-the-difference-between-backtracking-and-depth-first-search

    回溯是一种更通用的算法。

    深度优先搜索是与搜索树结构相关的回溯的一种特定形式。

    3.递归和回溯

    https://blog.csdn.net/fengchi863/article/details/80086915 这个补充的也挺好的。

    • 递归是一种算法结构,回溯是一种算法思想。
    • 一个递归就是在函数中调用函数本身来解决问题。
    • 回溯就是通过不同的尝试来生成问题的解,有点类似于穷举,但是和穷举不同的是回溯会“剪枝”。

    递归的一般过程:

    void f()  
    {  
         if(符合边界条件)  
         {  
            ///////  
            return;  
         }  
    
         //某种形式的调用  
         f();  
    }  

    回溯的一般过程:

    void DFS(int 当前状态)  
    {  
          if(当前状态为边界状态)  
          {  
            记录或输出  
            return;  
          }  
          for(i=0;i<n;i++)       //横向遍历解答树所有子节点  
          {  
               //扩展出一个子状态。  
               修改了全局变量  
               if(子状态满足约束条件)  
                {  
                  dfs(子状态)  
               }  
                恢复全局变量//回溯部分  
          }  
    }  

    BFS和DFS相似。BFS显式用队列,DFS隐式用栈,即递归。

    2020-4-3周五更新——————————————

    1.回溯的三种问题方式 

    https://segmentfault.com/a/1190000006121957

    1.有没有解

    2.有多少个解

    3.找出所有解是什么?

    这三种分别对应着不通的返回值,当然框架都是一样的吧。

    DFS它也是一种枚举的方法,暴力地走所有的路判断。

    第一种,返回值是true/false。
    第二种,求个数,设全局counter,返回值是void;求所有解信息,设result,返回值void。
    第三种,设个全局变量best,返回值是void。

    第一种:

    boolean solve(Node n) {
        if n is a leaf node {
            if the leaf is a goal node, return true
            else return false
        } else {
            for each child c of n {
                if solve(c) succeeds, return true
            }
            return false
        }
    }

    第二种:

    void solve(Node n) {
        if n is a leaf node {
            if the leaf is a goal node, count++, return;
            else return
        } else {
            for each child c of n {
                solve(c)
            }
        }
    }

    第三种:

    void solve(Node n) {
        if n is a leaf node {
            if the leaf is a goal node, update best result, return;
            else return
        } else {
            for each child c of n {
                solve(c)
            }
        }
    }

    好了,学习了。记住这个模板就ok了吧。

  • 相关阅读:
    Loj #6307. 「雅礼国庆 2017 Day1」Clique
    bzoj 4457: 游戏任务
    Codeforces 375 D Tree and Queries
    Codeforces 837 E Vasya's Function
    [POI2008]BLO
    Codeforces 451 E Devu and Flowers
    洛谷 P4318 完全平方数
    [JSOI2016]反质数序列
    bzoj 4320: ShangHai2006 Homework
    bzoj4454 C Language Practice
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/12494908.html
Copyright © 2011-2022 走看看