美文网首页
backtracking(回溯)

backtracking(回溯)

作者: 镜中无我 | 来源:发表于2019-10-19 11:14 被阅读0次

回溯法,是通过递归的方式穷举组合问题的所有可能解,关于这个问题的解决方法大致有如下步骤

  • 建立解矩阵,如果不知道可行解数量(有待探索),可以建立动态存储数据结构
  • 构建基本问题,首先检查解结构完备与否,如果完备返回解,或者记录解结构,另外如果存在提前结束的可能,可以贪婪的检查当前解结构是否已经违反解规则,如果是则提前结束
  • 基本问题的迭代结构,对于一般的组合问题,这个迭代的维度可能保持一致,当然也可能不一致,主要取决于原始问题的结构特征;每一次迭代需要进一步完备解结构,并且递归的进行下一步完备,值得注意的是:我们需要判断当前操作对横向和纵向的影响,如果是在解数量上(如是否有重复解等的)的影响,则需要在当前函数结构下对组合空间进行约束,如减少或者跳过重复项的选择;如果是在解结构上(比如解结构中不能出现重复的选择)的影响,则需要在递归调用之前改变约束组合空间,在递归之后释放约束。
    下面举例说明:

1. permutation问题

排列问题是一类典型的可以用backtracking解决的问题,给定n个数字(或者字),打印出所有可能的排列。数学上我们知道这个数量是一个阶乘,很好理解就是n次无放回的选择,这个操作结构如何在用backtracking实现呢?
按照回溯的思路:

solution[n!] //建立一个全局变量,当然也可以不这样做,只是需要在函数递归调用时不断传递解容器和当前解
void backtrack(current_solution, index){
if(current_solution is well_generated)
       print it or record it
       return
else if current_solution is bad_structure
       return // backtrack的迭代函数一般都是无返回值的
for index to space_size
       add space[index] to current_solution
       backtrack(current_solution, index+1)

如果给定一个初始的排列(结构中可能含有重复元素),此时可能会存在重复的解,原因在于横向空间中的重复会导致最终生成完全一致的解,并且递归的重复,所以必须在每一层次上改善解空间(不能对纵向产生影响),即记录已经迭代过的元素,避免重复!但是我们知道在解结构中是可能存在重复元素的,这时我们需要纵向的控制解结构,即通过记录已经构造的解中重复元素的数量来避免破坏解结构。下面的代码是个很好的例子:


    int  array [ 128 ];  //个别存入128个ASCII字元的出现次数
    char  solution [ MAX ];
     
    void  permutation ( int  k ,  int  n )
    {
        if  ( k  ==  n )
        {
            for  ( int  i = 0 ;  i < n ;  i ++)
                cout  <<  solution [ i ];
            cout  <<  endl ;
            return ;
        }
        
        for  ( int  i = 0 ;  i < 128 ;  i ++)    //列举每一个字母
            if  ( array [ i ] >  0 )        //还有字母剩下来,就要列举
            {
                array [ i ]--;          //用掉了一个字母
                
                solution [ k ] =  i ;     // char变数可以直接存入ascii数值
                permutation ( k + 1 ,  n );
     
                array [ i ]++;          //回收了一个字母
            }
    }
  1. next permutation
    相邻元素比较大小,直到前一元素小于后一元素,用遍历过的最小元素代替当前停止元素,然后将其他元素逆序输出。
  2. 有效括号最大长度
    下标存储法,通过记录下标来标记相邻的最大有效字串
  3. 字符串匹配问题一开始应该考虑用组合动态规划去解,考虑能否对0行和0列做初始化,如果能够初始化,则问题多半就能解决,一种求字符串之间距离的算法值得借鉴

相关文章

  • backtracking(回溯)

    回溯法,是通过递归的方式穷举组合问题的所有可能解,关于这个问题的解决方法大致有如下步骤 建立解矩阵,如果不知道可行...

  • backtracking回溯法

    http://www.csie.ntnu.edu.tw/~u91029/Backtracking.html 介绍回...

  • 回溯法

    摘自Backtracking回溯法(又称DFS,递归)全解,文章写得很不错!!! 回溯是啥 用爬山来比喻回溯,好比...

  • 22、Generate Parentheses

    题设 要点 回溯 backtracking 剪枝 明显地,可以用回溯法来解。判断条件为: 回溯法在每一步,本来应该...

  • [leetcode] [Tag Backtracking回溯]

    回溯法 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就...

  • 数据结构与算法-DFS/回溯

    回溯backtracking 回溯法思路的简单描述是:把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜...

  • 回溯法

    概述 Backtracking 回溯法实现 => DFS + 剪枝(跳过对某些一定不是解的子树) 可以把问题所有的...

  • 怎样应对IT面试与笔试-(八)

    Backtracking(回溯法) 51. N-Queens 经典的N皇后问题,将n个皇后放到n*n的棋盘上,使得...

  • 回溯算法

    回溯(backtracking): 有“通用解题法”之称。用它可以系统地搜索问题的所有解。它在问题的解空间树中,按...

  • 【算法】用回溯法(backtracking algorithm)

    什么是N-皇后问题? 说到这个N-皇后问题,就不得不先提一下这个历史上著名的8皇后问题啦。 八皇后问题,是一个古老...

网友评论

      本文标题:backtracking(回溯)

      本文链接:https://www.haomeiwen.com/subject/xycsmqtx.html