回溯法和分支定界法

概述

​ 要求解一个问题,最可靠的方法是:列出所有候选解,然后逐个检查,理论上在遍历了所有的候选解之后,就能得到所需要的解。但是,对于实际运用中的问题,候选解的规模庞大,即使使用速度最快的计算机,也很难在合理的时间内解决。

​ 回溯法和分支定界法师对复杂问题进行系统检查的系统方法。通过使用限制条件和界定函数,可以省去对很大一部分候选解的检查。

回溯法——深度优先搜索

​ 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的方法称为回溯法。满足回溯条件的某个状态的点称为活动节点, 而当前节点为E-节点, 一旦从E-节点不能达到新的节点,则活动节点被杀死,开始回溯。

算法思想

​ 回溯法思想是:首先定义问题的解空间,并把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。

基本思想类同于:

  • 图的深度优先搜索
  • 二叉树的后序遍历

算法步骤

1)定义问题的一个解空间,它包含了对问题实例的解。

2)用适合于搜索的方式组织解空间。

3)用深度优先搜索解空间,利用界定函数避免进入无解的子空间。

​ 回溯法的实现有一个有意义的特性:再继续搜索的同时产生解空间。在搜索过程中的任何时刻,仅保留从开始节点到当前E-节点。因此,回溯算法的空间需求为O(从开始节点起最长路径的长度)。

分值定界法——广度搜索优先

​ 类似于回溯法,也是一种在问题的解空间上搜索问题解的算法。但与回溯法不同,分值定界法一般用广度优先搜索或最小耗费方法来搜索解空间。

算法思想

​ 分支定界法的思想是:首先定义问题的解空间,并把问题的解空间转化成了图或者树的结构表示,然后使用广度优先搜索或者最小耗费(最大收益)策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。

基本思想类同于:

  • 图的广度优先搜索
  • 二叉树的层序遍历

​ 与回溯法的E-节点扩展方式不同,分值定界法在E-节点处,首先生成其满足条件的所有儿子结点(分支),然后再从当前的活动结点表中选择下一个E-节点。为了有效地选择下一E-节点,以加速搜索的进程,在每一个活动节点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活动节点表中选择一个最有利的节点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。

选择下一个E-结点的方式不同,则会有几种不同的分支搜索方式。

1)FIFO搜索

2)LIFO搜索

3)优先队列式搜索

算法步骤

1)定义问题的一个解空间,它包含了对问题实例的解。

2)用适合于搜索的方式组织解空间。

3)创建并维护一一张活动节点表,使用广度优先搜索解空间,利用界定函数避免进入无解的子空间。

回溯法和分支定界法的区别

《回溯法和分支定界法》

常见解空间

​ 不管是回溯法还是分支定界法,定义和组织解空间都是算法实现的前提,而常见的解空间有子集树和排列树。

子集树

​ 所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间成为子集树。遍历子集树的算法复杂度为Ω(2^n)。
​ 如0/1背包问题,从所给重量、价值不同的物品中挑选几个物品放入背包,使得在满足背包不超重的情况下,背包内物品价值最大。它的解空间就是一个典型的子集树。

回溯法搜索子集树的一般描述如下:

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);  
        }  
}

排列树

​ 所给的问题是确定n个元素满足某种性质的排列时,相应的解空间就是排列树。遍历排列树的算法复杂度为Ω(n!)。
​ 例如旅行售货员问题,一个售货员把几个城市旅行一遍,要求走的路程最小。它的解就是几个城市的排列,解空间就是排列树。
回溯法搜索排列树的一般描述如下:

void backtrack(int t) 
{
    if (t > n) 
        output(x);
    else
        for (int i = t; i < n; i++)
        {
            swap(x[t], x[i]);
            if (constraint(t) && bound(t))
                backtrack(t + 1);
            swap(x[t], x[i]);
        }
}
    原文作者:回溯法
    原文地址: https://blog.csdn.net/Mind_V/article/details/73741225
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞