【算法】回溯法——0-1背包问题

【算法】回溯法——0-1背包问题回溯法 nbsp nbsp nbsp nbsp 回溯法是一种非常有效的方法 有 通用的解题法 之称 它有点像穷举法 但是更带有跳跃性和系统性 他可以系统性的搜索一个问题的所有的解和任一解 回溯法采用的是深度优先策略 nbsp nbsp nbsp nbsp 回溯法在确定了解空间后 从根结点出发 以深度优先的方式搜索整个解空间 此时根结点成为一个活结点 并且成为当前的扩展结点 从扩展结点向纵向搜索新的结点 当算法搜索到了解空间数的任一结点 先判断该结点是

fishing-pan:https://blog.csdn.net/u0转载请注明出处】

回溯法

       回溯法是一种非常有效的方法,有“通用的解题法”之称。它有点像穷举法,但是更带有跳跃性和系统性,他可以系统性的搜索一个问题的所有的解和任一解。回溯法采用的是深度优先策略。

       回溯法在确定了解空间的结构后,从根结点出发,以深度优先的方式搜索整个解空间,此时根结点成为一个活结点,并且成为当前的扩展结点。每次都从扩展结点向纵向搜索新的结点,当算法搜索到了解空间的任一结点,先判断该结点是否肯定不包含问题的解(是否还能或者还有必要继续往下搜索),如果确定不包含问题的解,就逐层回溯;否则,进入子树,继续按照深度优先的策略进行搜索。当回溯到根结点时,说明搜索结束了,此时已经得到了一系列的解,根据需要选择其中的一个或者多个解即可。

       回溯法解决问题一般分为三个步骤;

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

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

       (3)以深度优先的方式搜索解空间。

回溯法的典型实例——0-1背包问题

      为了方便理解回溯法运算的流程,以0-1背包问题为例进行分析;

     问题:给定一个载重量为W,n个物品,物品的重量为Wi,价值为Vi,1<=i<=n,要求:把物品装入背包,并使包内物品价值最大。

    首先考虑贪心法,为了得到最大的价值,将所有物品按照单位价值(Vi/Wi)降序排列(例如采用希尔排序,时间复杂度为【算法】回溯法——0-1背包问题),在放入物品时优先考虑单位价值更高的物品。在搜索到空间树中的某个结点P时,已经确定了P及其前面的结点取值,进而判断从P继续扩展下去是否获得更大的价值,如果不能,该结点无需扩展,可以进行回溯了。下面的函数结合了贪心法判断从某一点扩展开去可能获得的最大的价值。

int Bound(int *Values, int *Weights,int n,int maxWeight,int num,int current_Weight,int current_profit) //--------------num为已选中的最后一个物品的编号,current_weight为现在的重量,current_profit为现有价值 { int i = num + 1; for (; i < n; i++) { if (current_Weight + Weights[i] < maxWeight) { current_profit += Values[i]; current_Weight += Weights[i]; } else { current_profit += (Values[i] / Weights[i])*(maxWeight - current_Weight); //计算是否有可能获得更大的价值,贪心策略; current_Weight = maxWeight; return current_profit; } } return current_profit; }

     下面的代码实现在解空间进行搜索的过程;

int *Knapsack(int *Values,int *Weights,int n,int maxWeight) { int *X = new int[n]; int *Y = new int[n]; int Weight = 0; int Profit = 0; int current_weight=0, current_profit=0; int i = 0; while (1) { while (i 
  
    = n) { Weight = current_weight; Profit = current_profit; i = n; for (int j = 0; j < n; j++) //------------把数组X挪给Y; { Y[j] = X[j]; } } //否则就是由于第i个物品在当前情况下无法放入背包 else { X[i] = UNSELECT; } while (Bound(Values, Weights, n, maxWeight, i, current_weight, current_profit) <= Profit)//如果不可能获得更大的价值,那么这个点就不需要进行扩展了; { while (i != 0 && X[i] != SELECT)//进行回溯 { i--; } if (i == 0) //当回溯到i=0时候,所有情况都遍历了 { return Y; } X[i] = UNSELECT; current_profit -= Values[i]; current_weight -= Weights[i]; } i++; } } 
  

       假设n=8,W=110;物品的价值和重量如下表(已按照单位价值排序);

物品 i 1 2 3 4 5 6 7 8
Vi 11 21 31 33 43 53 55 65
Wi 1 11 21 23 33 43 45 55

      那么问题的解空间就很明显了就是2的8次方个种问题的解的组合{(0,0,0,0,0,0,0,0)......(1,1,1,1,1,1,1,1)}。

      使用二叉树构建解空间,这里解空间的一个结点共有两个候选值0、1 。 0代表不放进背包中(右子树), 1代表放进背包中(左子树),如下图所示;

【算法】回溯法——0-1背包问题

 

      采用深度优先策略进行搜索,搜索的过程如下所示;

【算法】回溯法——0-1背包问题

       搜索得到的最终的结果就是159;

搜索过程分析(可以对照代码阅读)

      从第一个点开始向下扩展,扩展到将第四个点放入放入后,此时背包已经放入重量为56,价值为96。然后继续扩展,将第五个物品放入重量为89,价值为139。此时第六个物品无法继续放入,但是i=5的,也就是没有到达最后一个点,此时调用Bound()函数算出可能获得的最大的价值为164.66,那么继续向下扩展,但是无法放入物品了,继续调用Bound()判断是否向下扩展,直到最后一个物品也无法放入,确定此时搜索得到的可以获得的最大的价值为139,保存物品放入的选择。

      然后开始回溯,回溯遇到第一个放入背包的物品对应的节点,将其取0(把物品拿出背包,进入右子树)。此时比较背包剩余重量,发现第六个物品可以放入背包,放入后背包重量为99,价值为149。但是,第七个物品无法继续放入,那么调用Bound(),发现可能获得162的价值,大于139,继续向下扩展,直到最后一个物品也无法放入,确定此时搜索得到的可以获得的最大的价值为149>139,更新可获得的价值,并且保存物品放入的选择。

     继续回溯,直到回溯到根结点。此时的最大价值所对应的物品放入选择就是所求的解。

 算法复杂度分析

     在最坏的情况下,所搜索的结果是一个满二叉树,此时相当于采用的就是穷举法,时间复杂度为【算法】回溯法——0-1背包问题,而每次决定是否要讲n个物品放入背包都要进行比较,这一步的时间复杂度为n,所以最坏情况下时间复杂度为【算法】回溯法——0-1背包问题

已完。。。。

      

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176692.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午9:17
下一篇 2026年3月26日 下午9:18


相关推荐

  • access能接trunk口_交换机access与trunk口

    access能接trunk口_交换机access与trunk口理论知识 以太网端口二种链路类型 Access 和 Trunk Access 类型的端口 只能属于 1 个 VLAN 一般用于连接计算机的端口 Trunk 类型的端口 可以允许多个 VLAN 通过 可以接收和发送多个 VLAN 的报文 一般用于交换机之间连接的端口 交换机接口出入数据处理过程如下 一 1 Acess 端口收报文 收到一个报文 判断是否有 VLAN 信息 如果没有则打上端口的 PVID 并进行

    2026年3月19日
    1
  • 【教程】Linux 上从 0 部署 OpenClaw(能跑、能用、能反代)

    【教程】Linux 上从 0 部署 OpenClaw(能跑、能用、能反代)

    2026年3月13日
    2
  • idea配置springboot热部署终极解决办法,解决热部署失效问题

    idea配置springboot热部署终极解决办法,解决热部署失效问题idea配置springboot热部署终极解决办法,解决热部署失效问题1.添加maven依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</a…

    2022年5月21日
    109
  • 莫比乌斯反演

    莫比乌斯反演莫比乌斯函数值 intmobi intn intm 1 for inti 2 i i n i if n i 0 m 1 intk 0 do

    2026年3月20日
    2
  • AC自动机算法

    AC自动机算法AC 自动机简介 nbsp 首先简要介绍一下 AC 自动机 Aho Corasickauto 该算法在 1975 年产生于贝尔实验室 是著名的多模匹配算法之一 一个常见的例子就是给出 n 个单词 再给出一段包含 m 个字符的文章 让你找出有多少个单词在文章里出现过 要搞懂 AC 自动机 先得有字典树 Trie 和 KMP 模式匹配算法的基础知识 KMP 算法是单模式串的字符匹配算法 AC 自动机是多模式串的字符匹配算法

    2026年3月19日
    1
  • 达芬奇的密码[通俗易懂]

    达芬奇的密码[通俗易懂]写在前面郇山隐修会是一个确实存在的组织,是一个成立于1099年的欧洲秘密社团。1975年巴黎国家图书馆发现了被称作“秘密卷宗”的羊皮纸文献,才知道包括艾撒克。牛顿爵士、波提切利、维克多。雨果和列昂纳多。达。芬奇等众多人物均为郇山隐修会成员。人们所知的“天主事工会”是一个梵蒂冈教派——一个极度虔诚的罗马天主教派。该教派近来引起了诸多争议,因为有报道

    2022年7月11日
    29

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号