回溯算法的应用

news2025/8/4 1:29:37

基本思想:

回溯法从开始结点(根结点)出发,以深度优先方式搜索整个解空间。这个开始结点成为活结点,同时也成为当前的扩展结点。在当前扩展结点处,搜索向纵深方向移至一个新结点。这个新结点成为新的活结点,开成为当前扩展结点。如果在当前扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的活结点处,并使这个活结点成为当前扩展结点。回溯法以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已无活结点时为止。

例:对于n=3时的0-1背包问题,考虑下面的具体实例:w=[16,15,15],p=[45,25,25],c=30。

解空间:(三种物品的所有可能)

每一层的根节点对应某种物品。第一层是第一件物品,第二层时第二件物品,第三层是第三件物品。左子树表示装入下一件物品,右子树表示不装下一件物品

  • 开始时,根结点是唯一的活结点,也是当前扩展结点。在这个扩展结点处,可以沿纵深方向移至结点B或结点C。
  • 假设选择先移至结点B。此时,结点A和结点B是活结点,结点B成为当前扩展结点。由于选取了w1,故在结点B处剩余背包容量是r=14,获取的价值为45。
  • 从结点B处,可以移至结点D或E。由于移至结点D至少需要w2=15的背包容量,而现在仅有的背包容量是r=14,故移至结点D导致不可行解。搜索至结点E不需要背包容量,因而是可行的。从而选择移至结点E。此时,E成为新的扩展结点,结点A,B和E是活结点。在结点E处,r=14,获取的价值为45。
  • 从结点E处,可以向纵深移至结点J或K。移至结点J导致不可行解,而移向结点K是可行的,于是移向结点K,它成为新的扩展结点。由于结点K是叶结点,故得到一个可行解。这个解相应的价值为45。Xi的取值由根结点到叶结点K的路径唯一确定,即x=(1,0,0)。
  • 由于在结点K处已不能再向纵深扩展,所以结点K成为死结点。返回到结点E处。此时在结点E处也没有可扩展的结点,它也成为死结点。接下来又返回到结点B处。结点B同样也成为死结点,从而结点A再次成为当前扩展结点。
  • 结点A还可继续扩展,从而到达结点C。此时,r=30,获取的价值为0。
  • 从结点C可移向结点F或G。假设移至结点F,它成为新的扩展结点。结点A,C和F是活结点。在结点F处,r=15,获取的价值为25。从结点F,向纵深移至结点L处,此时,r=0,获取的价值为50。由于L是叶结点,而且是迄今为止找到的获取价值最高的可行解,因此记录这个可行解。
  • 结点L不可扩展,又返回到结点F处。按此方式继续搜索,可搜索遍整个解空间。搜索结束后找到的最好解是相应0-1背包问题的最优解。

回溯算法的装载问题

有一批共n个集装箱要装上两艘载重量分别为C_{1}C_{2}的轮船,其中,集装箱 i 的重量为W_{i}

\sum_{i=1}^{n}w_{i}=c_{1}+c_{2}
装载问题要求确定是否有一个合理的装载方案可将这n个集装箱装上这两艘轮船。如果有,找出一种装载方案。

基本思路:

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

(2)将剩余的集装箱装上第二艘轮船。
将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近c1。由此可知,装载问题等价于以下特殊的0-1背包问题。
将每个物品的装与不装化成解空间

回溯算法思想

算法maxLoading调用递归方法 backtrack(1)实现回溯搜索backtrack(i)搜索子集树中第i层子树。

类Loading 的数据成员记录子集树中结点信息

cw记录当前结点相应的装载重量

bestw记录当前最大装载重量。


在算法backtrack 中

当i≥n时,算法搜索至叶结点,其相应的装载重量为cw。如果cw>bestw ,则表示当前解优于当前最优解,此时应更新bestw。
当i≤n时,当前扩展结点Z是子集树的内部结点。该结点有:x[i]=1和x[i]=0两个儿子结点。

其左儿子结点表示x[i]=1的情形,仅当cw+w[i]≤c时进入左子树,对左子树递归搜索。

其右儿子结点表示x[i门=0的情形。由于可行结点的右儿子结点总是可行的,故进入右子树时不需检查可行性。 

public class Loading {
    //类数据成员
    static int n;   //集装箱数
    static int[] w;//集装箱重量数组
    static int c;//第一艘轮船的载重量
    static int cw;//当前载重量
    static int bestw;//当前最优载重量
    private static int maxLoading(int[]ww,int cc){
        //初始化数据成员
        n=ww.length-1;
        w=ww;
        c=cc;
        cw=0;
        bestw=0;
        
        //计算最优载重量
        backtrack(1);
        return bestw;
    }

    private static void backtrack(int i) {
        //搜索第i层结点
        if (i>n){//到达叶子节点
            if (cw>bestw) bestw =cw;  //更新最优载重
            return;
        }else{//未到达叶子节点
            if (cw+w[i]<=c){  //表示装上i层的节点后还能继续装
                cw+=w[i];//更新当前载重
                backtrack(i+1);//搜索下一层,直至搜索玩所有左子树,再遍历右子树
                cw-=w[i];//恢复遍历某个左节点之前的最初状态,便于遍历右子树
            }
            backtrack(i+1);//遍历右子树,无需装入,直接下一层
        }
    }

}

 上界函数

cw+r ≤ bestw表示货物总质量可以全部装进去,所以只需要左子树即可。

在算法中记录与当前最优值相应的当前最优解。在类Loading中增加两个私有数据成员α和 bestx,x用于记录从根至当前结点的路径, bestx记录当前最优解。算法搜索到达叶结点处,就修正bestx的值。
 

public class Loading2 {
    static int n;   //集装箱数
    static int[] w;//集装箱重量数组
    static int c;//第一艘轮船的载重量
    static int cw;//当前载重量(重量)
    static int bestw;//当前最优载重量(重量)
    static int r;//剩余集装箱重量、
    static int[] bestx;//记录当前最优解(路径)
    static int[]x;//当前解(路径)
    public static int maxLoading(int []w, int c, int[] bestx){
        //迭代回溯法
        //返回最优载重及其相应的解
        //初始化根节点
        int i =1;
        int n=w.length-1;
        int []x = new int[n+1];
        bestw =0;
        r=0;
        for(int j=0; j<=n; j++){
            r=r+w[j];
        }
        //搜索子树(进入子树)
        while (true){
            while (i<=n&&cw+w[i]<=c){//进入节点i的左子树,层数变为i+1
                r-=w[i];//剩余货物减少,节点i装入
                cw+=w[i];//当前载货量
                x[i]=1;//左子树,装入
                i++;//层数变化
            }
            if (i>n){
                //到达叶节点
                for (int j=1;j<=n;j++){
                    bestx[j]=x[j];//每次到叶节点更新最佳路径解
                }
                bestw = cw;//更新最优装载值
            }else {
                //进入右子树
                r-=w[i];//剩余货物减少,节点i装入,层数变为i+1
                x[i]=0;
                i++;
            }
            //从叶子节点返回根节点
            while (cw+r<=bestw){
                //剪枝回溯
                i--;//回溯
                while (i>0&&x[i]==0){//未到根节点且为右子树
                    r+=w[i];//从右子树返回
                    i--;
                }
                if (i==0) return bestw;//回到根节点
                //进入右子树
                x[i]=0;
                cw-=w[i];
                i++;
            }

        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15825.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据技术基础实验十五:Storm实验——实时WordCountTopology

大数据技术基础实验十五&#xff1a;Storm实验——实时WordCountTopology 文章目录大数据技术基础实验十五&#xff1a;Storm实验——实时WordCountTopology一、前言二、实验目的三、实验要求四、实验原理1、Topologies2、Spouts3、Bolts五、实验步骤1、导入依赖jar包2、编写代…

ffmpeg编译so

1.第一个坑&#xff1a;/bin/bash^M: bad interpreter: No such file or directory shell脚本报错/bin/bash^M: bad interpreter: No such file or directory&#xff0c;通过查阅资料得知&#xff0c;shell脚本格式必须是unix才行&#xff0c;但我这个脚本是在windows上编写完…

如何批量创建word文档并重命名?

如何批量创建word文档并重命名&#xff1f;大家请注意&#xff0c;我这里抛出的问题是批量创建word文档并重命名&#xff0c;重点在批量&#xff0c;并不是我们平时遇到的单纯创建一个或者几个word文档&#xff0c;而是批量创建几十上百个甚至几百上千个word文档。创建几个word…

英国博士后招聘|约克大学—核磁共振监测催化

英国约克大学博士后职位—核磁共振监测催化 约克大学&#xff08;University of York&#xff09;&#xff0c;建于1963年&#xff0c;是一所位于英国英格兰约克的研究型公立大学&#xff0c;英国罗素大学集团、世界大学联盟、N8大学联盟、白玫瑰大学联盟和江苏—英国高水平大学…

【开发心得】Java ftp开发注意事项

前言: 虽说已经2022年了&#xff0c;但是ftp上传方式还是有一定使用场景的&#xff0c;关于java的ftp上传下载实现&#xff0c;基本都指向了apache commont net 库。 代码实现可以参考:https://blog.csdn.net/tianshan2010/article/details/103690940 或者其他类似的文章&…

云服务--漏洞修复

1、Spring Security 身份认证绕过漏洞(CVE-2022-22978) Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。 Spring Security存在身份认证绕过漏洞 &#xff0c;当Spring Security中使用RegexRequestMatcher进行权限配置&#…

汽车云算力“竞速”,个性化进阶成新风向

配图来自Canva可画 随着产业互联网的持续推进&#xff0c;云服务逐渐深入各行各业&#xff0c;云服务厂商也专门推出各种面向特定行业的专属云&#xff0c;比如金融云、零售云、政务云等等。如今云服务厂商正把焦点深入到汽车领域&#xff0c;围绕“汽车云”展开新的角逐。 今…

LeetCode[662]二叉树的最大宽度

难度&#xff1a;中等 题目&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;返回树的 最大宽度 。 描述&#xff1a; 树的 最大宽度 是所有层中最大的 宽度 。 每一层的 宽度 被定义为该层最左和最右的非空节点&#xff08;即&#xff0c;两个端点&#xff09;之间的长…

麦子-linux驱动策略与框架

一、linux内核同步和互斥 信号量&#xff08;进程与进程&#xff09; 当进程A执行共享资源先加锁执行down表示占用资源&#xff0c;进程B想执行就会被dowm&#xff0c;导致陷入睡眠 当进程A行完了就会up释放资源&#xff0c;我们其他线程执行这个共享资源就不会被dowm睡眠 自旋…

蓝桥杯入门即劝退(十)反转链表

----------持续更新蓝桥杯入门系列算法实例------------ 如果你也喜欢Java和算法&#xff0c;欢迎订阅专栏共同学习交流&#xff01; 你的点赞、关注、评论、是我创作的动力&#xff01; -------希望我的文章对你有所帮助-------- 前言&#xff1a;如果有一定链表基础&#…

【图像处理】基于形状提取和模式匹配组合的面部特征点提取方法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

7天酒店斩获五洲钻石奖“年度投资价值酒店连锁品牌” 打造酒店投资极致性价比

近日&#xff0c;“2022文旅国际峰会暨第十五届世界酒店论坛”在海南隆重召开&#xff0c;300多位来自中外的业界精英和跨界企业家代表等受邀参加&#xff0c;齐聚行业盛会。同期&#xff0c;“第十四届五洲钻石奖”也正式揭晓&#xff0c;7天酒店在众多品牌中脱颖而出&#xf…

【原创】使用Golang的电商搜索技术架构实现

作者&#xff1a;黑夜路人 时间&#xff1a;2022年11月 一、背景&#xff1a; 现在搜索技术已经是非常主流的应用技术&#xff0c;各种优秀的索引开源软件已经很普遍了&#xff0c;比如 Lucene/Solr/Elasticsearch 等等主流搜索索引开源软件&#xff0c;让我们搭建一个优秀的…

项目管理如何有效进行?看这篇就够了

先放上一个项目管理流程图&#xff0c;纯手打&#xff0c;图有点长。 ​ 上面的流程图其实就已经清楚概括了项目管理的流程框架&#xff0c;按照这个逻辑去推进&#xff0c;一般来说就可以达到标准化的要求了。 将以上流程细化成具体的项目管理场景&#xff0c;大致可以分为7大…

【Java面试八股文宝典之基础篇】备战2023 查缺补漏 你越早准备 越早成功!!!——Day08

大家好&#xff0c;我是陶然同学&#xff0c;软件工程大三明年实习。认识我的朋友们知道&#xff0c;我是科班出身&#xff0c;学的还行&#xff0c;但是对面试掌握不够&#xff0c;所以我将用这100多天更新Java面试题&#x1f643;&#x1f643;。 不敢苟同&#xff0c;相信大…

6种MySQL数据库平滑扩容方案剖析

1. 扩容方案剖析 1.1 扩容问题 在项目初期&#xff0c;我们部署了三个数据库A、B、C&#xff0c;此时数据库的规模可以满足我们的业务需求。为了将数据做到平均分配&#xff0c;我们在Service服务层使用uid%3进行取模分片&#xff0c;从而将数据平均分配到三个数据库中。 如…

网络丢包,网络延迟?这款神器帮你搞定所有!

常用的 ping&#xff0c;tracert&#xff0c;nslookup 一般用来判断主机的网络连通性&#xff0c;其实 Linux 下有一个更好用的网络联通性判断工具&#xff0c;它可以结合ping nslookup traceroute 来判断网络的相关特性&#xff0c;这个命令就是 mtr。 mtr 全称 my tracerout…

2022年“移动云杯”算力网络应用创新大赛圆满落幕,百万大奖揭晓!

11 月 17-18 日&#xff0c;2022 年移动云开发者技术论坛暨“移动云杯”算力网络应用创新大赛总决赛在苏州举行。活动现场公布了 2022 年“移动云杯”算力网络应用创新大赛总决赛获奖名单。同时重磅发布了移动云 openAPI 2.0、首届移动云量子计算大赛。 三大赛道齐发力&#xf…

2022ICPC 网络赛第二场 E An Interesting Sequence

You should generate a sequence of positive integers of length n. Of course,this sequence needs to meet some requirements. ∀ i∈[1,n] ai​>1 ∀ i∈[2,n] gcd(ai−1​,ai​)1 a1​k(k>1) gcd(x,y) means the greatest common divisor of x and y. You n…

启明智显分享|4.3寸智能串口屏应用于充电桩

据数据显示&#xff0c;全球新能源汽车销量正大幅度增长&#xff0c;全球汽车电动化渗透率也由0.8%增长到7.74%&#xff0c;这不仅意味着汽车产业电动化浪潮的来临&#xff0c;也证实了我国新能源汽车行业正处于高速发展状态。随着电动汽车销售量与保有量的迅速增长&#xff0c…