趣学算法系列-回溯法

趣学算法系列-回溯法

声明:本系列为趣学算法一书学习总结内容,在此推荐大家看这本算法书籍作为算法入门,
原作者博客链接,本书暂无免费电子版资源,请大家支持正版

第五章 回溯法

回溯法是一种选优搜索法,按照选优条件深度优先搜索,以达到目标。当搜索到某一步
时,发现原先选择并不是最优或达不到目标,就退回一步重新选择,这种走不通就退回再走
的技术称为回溯法
回溯法是一种“ 能进则进,进不了则换,换不了则退”的搜索方法。
- 回溯法的算法要素
首先要确定解的形式,定义问题的解空间
解空间:顾名思义,就是由所有可能解组成的空间。解空间越小,搜索效率越高。
一个问题的解空间通常由很多可能解组成,一定的组织结构搜索最优解,
如果把这种组织结构用树形象地表达出来,就是解空间树。
趣学算法系列-回溯法_第1张图片
隐约束指对能否得到问题的可行解或最优解做出的约束。如果不满足隐约束,
就说明得不到问题的可行解或最优解,那就没必要再沿着该结点的分支进行搜索了,
相当于把这个分支剪掉了
显约束可以控制解空间大小,隐约束是在搜索解空间过程中判定可行解或最优解的。
- 回溯法解题秘籍
(1)定义解空间 确定解空间包括解的组织形式和显约束(范围限定)
(2)确定解空间的组织结构 通常用解空间树形象的表达(只是辅助理解并不是真的树)
(3)搜索解空间 按照深度优先搜索,根据限制条件,搜索问题的解
- 回溯法的典型应用
        n皇后问题
        地图着色问题


  • 实际案例分析-n皇后问题

  • 问题描述

    在 n×n 的棋盘上放置彼此不受攻击的 n 个皇后。按照国际象棋的规则,皇后可以攻击与之在同一行、同一列、同一斜线上的棋子。设计算法在 n×n 的棋盘上放置 n 个皇后,使其彼此不受攻击
    趣学算法系列-回溯法_第2张图片

  • 问题分析

    我们在第 i 行第 j 列放置一个皇后,那么第 i 行的其他位置(同行),那么第 j 列的其他位置(同列),同一斜线上的其他位置,都不能再放置皇后
    趣学算法系列-回溯法_第3张图片
    我们不可能杂乱无章地尝试每个位置,要有求解策略。我们可以以行为主导:
    在第 1 行第 1 列放置第 1 个皇后。
    在第 2 行放置第 2 个皇后。第 2 个皇后的位置不能和第1个皇后同列、同斜线,不用再判断是否同行了,因为我们每行只放置一个,本来就已经不同行。
    在第 3 行放置第 3 个皇后,第 3 个皇后的位置不能和前 2 个皇后同列、同斜线。
    ……
    在第 t 行放置第 t 个皇后,第 t 个皇后的位置不能和前 t−1 个皇后同列、同斜线。

  • 算法设计

    (1)定义问题的解空间
    n 皇后问题解的形式为 n 元组: {x1, x2,…, xi,…, xn},分量 xi 表示第 i 个皇后放置在第 i 行第 xi 列
    例如 x2=5,表示第 2 个皇后放置在第 2 行第 5列
    (2)解空间的组织结构
    n 皇后问题的解空间是一棵 m( m=n)叉树,树的深度为 n,如图 5-68 所示。
    图不理解,请看树结构中连线的标注部分
    趣学算法系列-回溯法_第4张图片
    (3)搜索解空间
    限制条件
    在第 t 行放置第 t 个皇后时,第 t 个皇后的位置不能和前 t−1 个皇后同列、同斜线。第 i
    个皇后和第 j 个皇后不同列,即 xi!=xj,并且不同斜线|i−j| != |xi−xj|。
    看图分析(斜线规律)
    趣学算法系列-回溯法_第5张图片

  • 完美图解

    为了简单明了,我们在 4× 4 的棋盘上放置 4个皇后,使其彼此不受攻击,如图 5-69 所示
    开始搜索第 1 层(t=1)
    扩展 1 号结点,首先判断 x1=1 是否满足约束条件,因为之前还未选中任何结点,满足
    约束条件。令 x[1]=1,生成 2 号结点
    趣学算法系列-回溯法_第6张图片
    扩展 2 号结点( t=2)
    判断 x2=1 不满足约束条件,因为和之前放置的第 1 个皇后同列;考查 x2=2 也不满
    足约束条件,因为和之前放置的第 1 个皇后同斜线;考查 x2=3 满足约束条件令 x[2]=3,生成 3 号结点
    趣学算法系列-回溯法_第7张图片
    扩展 3 号结点( t=3)
    首先判断 x3=1 不满足约束条件,因为和之前放置的第 1 个皇后同列;考查 x3=2 也不满足约
    束条件,因为和之前放置的第 2 个皇后同斜线;考查 x2=3 不满足约束条件,因为和之前放置的
    第 2 个皇后同列;考查 x3=4 也不满足约束条件,因为和之前放置的第 2 个皇后同斜线; 3 号结
    点的所有孩子均已考查完毕, 3 号结点成为死结点。向上回溯到 2 号结点
    趣学算法系列-回溯法_第8张图片
    后续过程略,直接看最终的结果图
    趣学算法系列-回溯法_第9张图片
    趣学算法系列-回溯法_第10张图片
    趣学算法系列-回溯法_第11张图片

  • 伪代码详解

    (1)约束函数

    bool Place(int t) //判断第 t 个皇后能否放置在第 i 个位置
    {
    bool ok=true;
    for(int j=1;j//判断该位置的皇后是否与前面 t-1 个已经放置的皇后冲突
    {
    if(x[t]==x[j]||t-j==fabs(x[t]-x[j]))//判断列、对角线是否冲突
    {
    ok=false;
    break;
    }
    }
    return ok;
    }

    (2)按约束条件搜索求解

    void Backtrack(int t)
    {
    if(t>n) //如果当前位置为 n,则表示已经找到了问题的一个解
    {
    countn++;
    for(int i=1; i<=n;i++) //打印选择的路径
    cout<" ";
    cout<cout<<"----------"<else
    for(int i=1;i<=n;i++) //分别判断 n 个分支,特别注意 i 不要定义为全局变量,否则
    递归调用有问题
    {
    x[t]=i;
    if(Place(t))
    Backtrack(t+1); //如果不冲突的话进行下一行的搜索
    }
    }
  • 实战演练
    //program 5-4
    
    #include 
    
    
    #include //求绝对值函数需要引入该头文件
    
    
    #define M 105
    
    using namespace std;
    int n; //n 表示 n 个皇后
    int x[M]; //x[i]表示第 i 个皇后放置在第 i 行第 x[i]列
    int countn; //countn 表示 n 皇后问题可行解的个数
    bool Place(int t) //判断第 t 个皇后能否放置在第 i 个位置
    {
    bool ok=true;
    for(int j=1;j//判断该位置的皇后是否与前面 t-1 个已经放置的皇后冲突
    {
    if(x[t]==x[j]||t-j==fabs(x[t]-x[j]))//判断列、对角线是否冲突
    {
    ok=false;
    break;
    }
    }
    return ok;
    }
    void Backtrack(int t)
    {
    if(t>n) //如果当前位置为 n,则表示已经找到了问题的一个解
    {
    countn++;
    for(int i=1; i<=n;i++) //打印选择的路径
    cout<" ";
    cout<cout<<"----------"<else
    for(int i=1;i<=n;i++) //分别判断 n 个分支,特别注意 i 不要定义为全局变量,否则
    递归调用有问题
    {
    x[t]=i;
    if(Place(t))
    Backtrack(t+1); //如果不冲突的话进行下一行的搜索
    }
    }
    int main()
    {
    cout<<"请输入皇后的个数 n: ";
    cin>>n;
    countn=0;
    Backtrack(1);
    cout <<"答案的个数是: "<return 0;
    }
  • 算法时间复杂度分析

    (1)时间复杂度在最坏情况下回搜索到每一个叶子结点, 叶子个数为 n的n次方, 故耗时为 O(n^n)。仅为估算并不准确
    (2)空间复杂度:使用 x[]数组记录该最长路径作为可行解,所以该算法的空间复杂度为 O(n)。

  • 算法优化方向
    解决方案的解空间树 此题解空间我们使用了不同行作为显约束。隐约束为不同列、不同斜线。
    趣学算法系列-回溯法_第12张图片
    上边的方面时间复杂度的复杂主要是由于解空间的结构复杂,如何有更好的思路优化解空间?
    如果我们把显约束定为不同行、不同列,隐约束不同斜线,那解空间是怎样的呢?
    趣学算法系列-回溯法_第13张图片
    如此对比解空间的大小缩小了很多,合理分析限制条件可以得到更好的解决方案。
  • 你可能感兴趣的:(算法分析)