【算法分析与设计】回溯法(上)

简介: 【算法分析与设计】回溯法(上)

一、学习要点

  理解回溯法的深度优先搜索策略。

  掌握用回溯法解题的算法框架

  (1)递归回溯

  (2)迭代回溯

  (3)子集树算法框架

  (4)排列树算法框架

  通过应用范例学习回溯法的设计策略。

  (1)装载问题;

  (2)批处理作业调度;

  (3)符号三角形问题

  (4)n后问题;

  (5)0-1背包问题;

  (6)最大团问题;

  (7)图的m着色问题

  (8)旅行售货员问题

  (9)圆排列问题

  (10)电路板排列问题

  (11)连续邮资问题


1.1 回溯法

  有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法

  回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种方法 适用于解一些组合数相当大的问题

  回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯否则,进入该子树,继续按深度优先策略搜索


1.2 问题的解空间

  问题的解向量:回溯法希望一个问题的解能够表示成一个n元式(x1,x2,…,xn)的形式。

  显约束对分量xi的取值限定

  隐约束为满足问题的解而对不同分量之间施加的约束

  解空间:对于问题的一个实例,解向量满足显式约束条件的所有多元组,构成了该实例的一个解空间

  注意:同一个问题可以有多种表示,有些表示方法更简单,所需表示的状态空间更小(存储量少,搜索方法简单)。

  n=3时的0-1背包问题用完全二叉树表示的解空间:


1.3 0-1背包问题的解空间

  问题的解空间应该至少包含问题的一个(最优)解

  对于n种可选择物品的0-1背包问题,其解空间由长度为n的0-1向量组成

  当n=3时,其解空间为{(0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1,1,0),(1,1,1)}

  解空间其实就是解的集合


1.4 旅行售货员问题的解空间

  问题:某售货员要到若干城市去推销商品,已知各城市之间的路程(旅费)。他要选择一条从驻地出发,经过每个城市一遍,然后回到驻地的路线,使总的路程(总旅费)最小。


1.5 生成问题状态的基本方法

  白结点:未被访问到的结点

  灰结点:一个自身已生成但其儿子还没有全部生成的节点称做灰结点

  黑结点:一个所有儿子已经产生的结点称做黑结点

  深度优先的问题状态生成法:如果对一个扩展结点R,一旦产生了它的一个儿子C,就把C当做新的扩展结点。在完成对子树C(以C为根的子树)的穷尽搜索之后,将R重新变成扩展结点,继续生成R的下一个儿子(如果存在)。

  宽度优先的问题状态生成法:在一个扩展结点变成黑结点之前,它一直是扩展结点。

  回溯法为了避免生成那些不可能产生最佳解的问题状态,要不断地利用限界函数(bounding function)来处死那些实际上不可能产生所需解的活结点,以减少问题的计算量。具有限界函数的深度优先生成法称为回溯法


二、回溯法的基本思想

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

  (2)确定易于搜索的解空间结构

  (3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索

  常用剪枝函数

  用约束函数在扩展结点处剪去不满足约束的子树

  用限界函数剪去得不到最优解的子树

  用回溯法解题的一个显著特征是在搜索过程中动态产生问题的解空间在任何时刻,算法只保存从根结点到当前扩展结点的路径。如果解空间树中从根结点到叶结点的最长路径的长度为h(n),则回溯法所需的计算空间通常为O(h(n))。而显式地存储整个解空间则需要O(2h(n))或O(h(n)!)内存空间。


三、回溯算法的适用条件

  在结点<x1,x2,…,xk>处P(x1,x2,…,xk)为真。即向量<x1,x2,…,xk>满足某个性质,则有P(x1,x2,…,xk+1)-> P(x1,x2,…,xk) 0<k<n。称之为多米诺性质

  ┐ P(x1,x2,…,xk) ->┐ P(x1,x2,…,xk+1) 0<k<n

  k维向量不满足约束条件,扩张向量到k+1维仍旧不满足,才可以进行回溯


四、递归回溯

  回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法

void backtrack (int t)
{
       if (t>n) output(x);
       else
         for (int i=f(n,t);i<=g(n,t);i++) {
           x[t]=h(i);
           if (constraint(t)&&bound(t)) backtrack(t+1);
           }
}

五、迭代回溯

  采用 树的非递归深度优先遍历算法,可将回溯法表示为一个非递归迭代过程

void iterativeBacktrack ()
{
  int t=1;
  while (t>0) {
    if (f(n,t)<=g(n,t)) 
      for (int i=f(n,t);i<=g(n,t);i++) {
        x[t]=h(i);
        if (constraint(t)&&bound(t)) {
          if (solution(t)) output(x);
          else t++;}
        }
    else t--;
    }
}

六、子集树与排列树

  当所给问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间树称为子集树(2n)。

  当所给问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树(n!)。

  遍历子集树需O(2n)计算时间

void backtrack (int t)
{
  if (t>n) output(x);
    else
      for (int i=0;i<=1;i++) {
        x[t]=i;
        if (legal(t)) backtrack(t+1);
      }
}

  遍历排列树需要O(n!)计算时间

void backtrack (int t)
{
  if (t>n) output(x);
    else
      for (int i=t;i<=n;i++) {
        swap(x[t], x[i]);
        if (legal(t)) backtrack(t+1);
        swap(x[t], x[i]);
      }
} 

七、装载问题

  有一批共n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,且

  装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船。如果有,找出一种装载方案。

  将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近。由此可知,装载问题等价于以下特殊的0-1背包问题。

  用回溯法设计解装载问题的O(2n)计算时间算法。在某些情况下该算法优于动态规划算法

  当n=3,c1=c2=50,且w=[10,40,40]

  如果w=[20,40,40]

  最优装载方案

  (1)首先将第一艘轮船尽可能装满

  (2)将剩余的集装箱装上第二艘轮船

  解空间:子集树

  可行性约束函数(选择当前元素):

  上界函数(不选择当前元素)

  当前载重量cw+剩余集装箱的重量r≤当前最优载重量bestw

void backtrack (int i)
   {// 搜索第i层结点
      if (i > n)  // 到达叶结点
      更新最优解bestx,bestw;return;
      r -= w[i];
      if (cw + w[i] <= c) {// 搜索左子树
         x[i] = 1;
         cw += w[i];
         backtrack(i + 1);
         cw -= w[i];      }
      if (cw + r > bestw)  {
         x[i] = 0;  // 搜索右子树
         backtrack(i + 1);      }
      r += w[i];
   }


八、批处理作业调度问题

  n个作业{1, 2, …, n}要在两台机器上处理,每个作业必须先由机器1处理,然后再由机器2处理,机器1处理作业i所需时间为ai,机器2处理作业i所需时间为bi(1≤i≤n),批处理作业调度问题要求确定这n个作业的最优处理顺序,使得从第1个作业在机器1上处理开始,到最后一个作业在机器2上处理结束所需时间最少。

  显然,批处理作业的一个最优调度应使机器1没有空闲时间,且机器2的空闲时间最小。可以证明,存在一个最优作业调度使得在机器1和机器2上作业以相同次序完成

  例:三个作业{1, 2, 3},这三个作业在机器1上所需的处理时间为(2, 3, 2),在机器2上所需的处理时间为(1, 1, 3),则最佳调度方案是(1, 3, 2)、(3, 1, 2)和(3, 2, 1),其完成时间为8。

  解空间:排列树

void Flowshop::Backtrack(int i)
{
   if (i > n) {
       for (int j = 1; j <= n; j++)
         bestx[j] = x[j];
       bestf = f;
       }
   else
      for (int j = i; j <= n; j++) {
         f1+=M[x[j]][1];
         f2[i]=((f2[i-1]>f1)?f2[i-1]:f1)+M[x[j]][2];
         f+=f2[i];
         if (f < bestf) {
            Swap(x[i], x[j]);
            Backtrack(i+1);
            Swap(x[i], x[j]);
            }
         f1- =M[x[j]][1];
         f- =f2[i];
         }
}

class Flowshop {
   friend Flow(int**, int, int []);
   private:
      void Backtrack(int i);
      int  **M,    // 各作业所需的处理时间
              *x,     // 当前作业调度
        *bestx,    // 当前最优作业调度
             *f2,    // 机器2完成处理时间
              f1,    // 机器1完成处理时间
               f,     // 完成时间和
         bestf,    // 当前最优值
               n;   // 作业数}; 


目录
打赏
0
1
0
0
7
分享
相关文章
别急着上算法,咱先把数据整明白:大数据分析的5个基本步骤,你都搞对了吗?
别急着上算法,咱先把数据整明白:大数据分析的5个基本步骤,你都搞对了吗?
114 4
员工行为监控软件中的 Go 语言哈希表算法:理论、实现与分析
当代企业管理体系中,员工行为监控软件已逐步成为维护企业信息安全、提升工作效能的关键工具。这类软件能够实时记录员工操作行为,为企业管理者提供数据驱动的决策依据。其核心支撑技术在于数据结构与算法的精妙运用。本文聚焦于 Go 语言中的哈希表算法,深入探究其在员工行为监控软件中的应用逻辑与实现机制。
103 14
境内深度合成服务算法备案通过名单分析报告
本报告基于《境内深度合成服务算法备案通过名单》,分析了2023年6月至2025年3月公布的10批备案数据,涵盖属地分布、行业应用及产品形式等多个维度。报告显示,深度合成算法主要集中于经济发达地区,如北京、广东、上海等地,涉及教育、医疗、金融、娱乐等多行业。未来趋势显示技术将向多模态融合、行业定制化和安全合规方向发展。建议企业加强技术研发、拓展应用场景、关注政策动态,以在深度合成领域抢占先机。此分析旨在为企业提供参考,助力把握技术发展机遇。
境内深度合成服务算法备案通过名单分析报告
从公布的前十一批其他算法备案通过名单分析
2025年3月12日,国家网信办发布算法备案信息,深度合成算法通过395款,其他算法45款。前10次备案中,深度合成算法累计3234款,其他类别647款。个性化推送类占比49%,涵盖电商、资讯、视频推荐;检索过滤类占31.53%,用于搜索优化和内容安全;调度决策类占9.12%,集中在物流配送等;排序精选类占8.81%,生成合成类占1.55%。应用领域包括电商、社交媒体、物流、金融、医疗等,互联网科技企业主导,技术向垂直行业渗透,内容安全和多模态技术成新增长点。未来大模型检索和多模态生成或成重点。
从公布的前十一批其他算法备案通过名单分析
从第十批算法备案通过名单中分析算法的属地占比、行业及应用情况
2025年3月12日,国家网信办公布第十批深度合成算法通过名单,共395款。主要分布在广东、北京、上海、浙江等地,占比超80%,涵盖智能对话、图像生成、文本生成等多行业。典型应用包括医疗、教育、金融等领域,如觅健医疗内容生成算法、匠邦AI智能生成合成算法等。服务角色以面向用户为主,技术趋势为多模态融合与垂直领域专业化。
企业监控软件中 Go 语言哈希表算法的应用研究与分析
在数字化时代,企业监控软件对企业的稳定运营至关重要。哈希表(散列表)作为高效的数据结构,广泛应用于企业监控中,如设备状态管理、数据分类和缓存机制。Go 语言中的 map 实现了哈希表,能快速处理海量监控数据,确保实时准确反映设备状态,提升系统性能,助力企业实现智能化管理。
78 3
从第九批深度合成备案通过公示名单分析算法备案属地、行业及应用领域占比
2024年12月20日,中央网信办公布第九批深度合成算法名单。分析显示,教育、智能对话、医疗健康和图像生成为核心应用领域。文本生成占比最高(57.56%),涵盖智能客服、法律咨询等;图像/视频生成次之(27.32%),应用于广告设计、影视制作等。北京、广东、浙江等地技术集中度高,多模态融合成未来重点。垂直行业如医疗、教育、金融加速引入AI,提升效率与用户体验。
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
Java中的算法优化与复杂度分析
在Java开发中,理解和优化算法的时间复杂度和空间复杂度是提升程序性能的关键。通过合理选择数据结构、避免重复计算、应用分治法等策略,可以显著提高算法效率。在实际开发中,应该根据具体需求和场景,选择合适的优化方法,从而编写出高效、可靠的代码。
119 6

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问