当前位置:   article > 正文

回溯法-------0-1背包问题(DFS、剪枝函数)_回溯法求解0-1背包问题

回溯法求解0-1背包问题

目录

一  回溯法概述

二 深度优先搜索策略(DFS)

1 树中的深度优先遍历

2 图中的深度优先遍历

三 剪枝函数

四 0-1背包问题

1 问题描述:

2 问题求解:

3 举例说明:

4 算法实现

5 结果展示:

五 复杂度分析


一  回溯法概述

回溯法的思路主要可以概述为以下2点:

(1)问题的解空间转化成了或者的结构

(2)使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行或者最优解,并在搜索过程中用剪枝函数避免无效搜索。

二 深度优先搜索策略(DFS)

深度优先遍历一般只在图和树中涉及,当然,树是图的一种特殊结构。DFS简要来说就是对每一个可能的分支路径深入到不能再深入为止,且不能重复遍历,即每个节点只能遍历一次

下边举两个例子 说明一下DFS,帮助理解。

1 树中的深度优先遍历

如图所示:是一个二叉树,其深度遍历的顺序为:ABD E CF G

遍历路径如图中棕色箭头所示。具体遍历步骤如下:

(1)先从A点出发,既可以选择遍历B也可以选择遍历C,图中选择B

(2)从B点出发,既可以选择遍历D也可以选择遍历E,图中选择D

(3)到达D点后,没有可以继续深入的节点,则向上回溯,到达B点,选择B点还没有遍历的其他节点,图中选择E;

(4)到达E点后,没有可以继续深入的节点,则向上回溯到达B,仍没有可以继续深入的节点,向上回溯到A,选择A还没有遍历的其他节点,图中选择C

(5)到达C点后,既可以选择遍历F也可以选择遍历G,图中选择F;

  (6)  到达F点后,没有可以继续深入的节点,则向上回溯到C,选择C点还没有遍历的其他节点,图中选择G;

  (7)  达到G点后,没有可以继续深入的节点,则向上回溯到C,仍没有可以继续深入的节点,则向上回溯到A,此时A没有还未遍历的节点,遍历到此结束。

2 图中的深度优先遍历

如图所示,是一个无向图。其深度遍历顺序为:ABDFECGH

遍历路径如图中棕色箭头所示。具体遍历步骤如下:

(1)先从A点出发,既可以选择遍历B、C也可以选择遍历H,图中选择B

(2)从B点出发,既可以选择遍历D也可以选择遍历E,图中选择D

(3)到达D点后,向下继续深入,图中选择F;

  (4)  到达F点后,向下继续深入,图中选择E;

(5)到达E点后,没有可以继续深入的节点,则向上回溯,到达F点,仍没有可以继续深入的节点,向上回溯到D,到达D点,仍没有可以继续深入的节点,向上回溯到B,到达B点,仍没有可以继续深入的节点,向上回溯到A,选择A点还没有遍历的其他节点,图中选择C;

(6)到达C点后,向下继续深入,图中选择G

(7)到达G点后,没有可以继续深入的节点,则向上回溯到C;

  (8)  到达C点后,没有可以继续深入的节点,则向上回溯到A,选择A点还没有遍历的其他节点,图中选择H;

  (9)  达到H点后,没有可以继续深入的节点,则向上回溯到A,此时A没有还未遍历的节点,遍历到此结束。

三 剪枝函数

剪枝函数,顾名思义就是,剪去无用的枝条,即在进行遍历时,提前减去不必要的分支,避免无效遍历。其根本目的,是要减少搜索的次数,使程序运行的时间减少,提高算法效率。

应用剪枝优化的核心问题是设计剪枝判断方法,即确定哪些枝条应当舍弃,哪些枝条应当保留的方法。

剪枝算法按照其判断思路可大致分成两类:可行性剪枝及最优性剪枝。

可行性剪枝: 该方法判断继续搜索能否得出答案,如果不能直接回溯。

最优性剪枝:它记录当前得到的最优值,如果当前结点已经无法产生比当前更优的解时,可以提前回溯。

四 0-1背包问题

1 问题描述:

有N件物品和一个容量为C的背包。第i件物品的价值是P[i],重量是W[i]。求解将哪些物品装入背包可使价值总和最大。所谓0-1背包,表示每一个物品不能拆解,要么装入,要么不装入。

2 问题求解:

0-1背包问题是求最优解的问题。在考虑将物品放进背包的原则是:单位价值(P[i]/W[i])越大的,尽量提前放进背包中(即将性价比更高的物品更早装进背包);但是限制条件是,所装物品必须是完整的且重量不能超过背包承重能力。

问题转化:

按照上述思路,先将各物品按照单位价值递减的顺序排序,其次进行判断是否在承重范围值内

定义:CW(current weight)表示当前重量,CP(current price)表示当前价值,

根节点代表扩展结点 ,其余每一层代表一个物品,越靠近根节点,单位价值越高。选中该物品,即搜索左子树,进行判断。具体执行操作如下所示:

1)先计算所有物品的单位价值,将其进行降序排列

2)排列之后,从根节点(扩展节点)出发;

3)搜索左子树,判断是否满足约束条件(物品装入背包?) 

           若选中物品(可行解),CW+=W[i]CP+=P[i],继续向下遍历

           直至遇到不可行解时,开始向上回溯,取出最后一个装入的物品,进入右子树:

4)进入右子树,首先计算当前节点的上界bound(i)

           bound(i)小bestp,剪去右子树,继续向上回溯

          否则进行步骤(3

5)遇到叶子节点,比较当前价值与bestpCP>bestp,则bestp进行更新;

6)直到遍历完所有的节点(除剪枝部分外)。

3 举例说明:

已知:p[]={45,25,24};    w[]={16,15,15};背包容量为30,求最优价值?

(1)先将这四件物品的单位价值算出来,按照单位价值降序排列。刚好顺序和原始顺序一致。

(2)开始进行遍历并判断是否装入,

具体步骤如下:(B1,B2,都指的是物品B,C1,C2,C3,C4都指的是物品C ,依此类推  主要是为了区分结点  便于叙述)

首先 物品B1 装入符合条件(最大重量不超过背包容量30的要求),遍历其左子树,此时CW = 16,CP = 45;

到达B1点后,遍历其左子树,发现剩余容量r = 14,C1无法装入背包,剪去B1-C1这条枝;

进入右子树,到达C2后,计算bound(i) = 68.3>45继续向下遍历。遍历其左子树,发现剩余容量r = 14,D3无法装入背包,剪去C2-D3这条枝;

进入右子树,到达C2后,遇到叶子节点,此时bestp = 45。记录该值。

向上回溯,取出最后一个装入的物品B1,到达A,进入右子树,到达B2;计算bound(i) = 49>45,继续向下遍历;此时CW = 0,CVP= 0;

遍历左子树,到达C3,此时CW = 15,CP= 25;剩余容量r =15。

继续向下遍历 ,到达D5,此时D5可以装入包中,CW = 30,CP = 49。此时CP>bestp = 45,进行更新bestp; bestp = 49。记录bestp和当前包中物品

由于还有其他结点没有遍历完成,继续进行回溯。

取出最后一个装入的物品D5,到达C3,进入右子树,到达D6,此时CW = 15,CP= 25;到达了叶子节点 判断是否需要更新bestp。由于CP= 25<bestp,不用更新。

继续向上回溯,去除最后一个装入的物品C3,到达B2,向右进行遍历,进入右子树,到达C4,计算bound(i) = 48<bestp,不用向下遍历,进行剪枝。

此时所有结点已经完全遍历,最有价值为49,装入CD即可。

遍历过程如图所示:(图中68.3应该位67.4,bound = 45+14*(24/15)=67.4)

4 算法实现

  1. import java.util.Arrays;
  2. import java.lang.annotation.ElementType;
  3. /**
  4. * Author: PuTongFish
  5. */
  6. public class Knapsack {
  7. private static class Element implements Comparable {
  8. int id;//物品编号
  9. double d;
  10. private Element(int idd, double dd) {
  11. id = idd;
  12. d = dd;
  13. }
  14. @Override
  15. public int compareTo(Object o) {
  16. double xd = ((Element)o).d;
  17. if (d < xd) return -1;
  18. if (d == xd) return 0;
  19. return 1;
  20. }
  21. public boolean equals(Object x) {
  22. return d == ((Element) x).d;
  23. }
  24. }
  25. static double c;
  26. static int n;
  27. static double[] p;
  28. static double[] w;
  29. static double cw;
  30. static double cp;
  31. static double bestp;
  32. public static double Knapsack(double[] pp,double[] ww,double cc) {
  33. c = cc;
  34. n = pp.length;
  35. cw = 0.0;
  36. cp = 0.0;
  37. bestp = 0.0;
  38. Element[] q = new Element[n];
  39. for (int i = 1; i <= n; i++) {
  40. q[i - 1] = new Element(i, pp[i] / ww[i]);
  41. }
  42. //排序
  43. //MergeSort.mergeSort(q);
  44. for (int i = 1; i <= n; i++) {
  45. for (int j = 1; j <= n - i; j++) {
  46. if (q[j - 1].d < q[j].d) {
  47. Element temp = q[j - 1];
  48. q[j - 1] = q[j];
  49. q[j] = temp;
  50. }
  51. }
  52. }
  53. p = new double[n + 1];
  54. w = new double[n + 1];
  55. for (int i = 1; i <= n; i++) {
  56. p[i] = pp[q[n - i].id];
  57. w[i] = ww[q[n - i].id];
  58. }
  59. Backtrack(1);
  60. return bestp;
  61. }
  62. private static void Backtrack(int i){
  63. if (i > n) {
  64. //到达叶结点
  65. bestp = cp;
  66. return;
  67. }
  68. if (cw + w[i] <= c) { //进入左子树
  69. cw += w[i];
  70. cp += p[i];
  71. Backtrack(i + 1);
  72. cw -= w[i];
  73. cp -= p[i];
  74. }
  75. // float u=Bound(i + 1);
  76. // float bb=bestp;
  77. //当前的界是否大于背包当前的值
  78. if (Bound(i + 1) > bestp) { //进入右子树
  79. Backtrack(i + 1);
  80. }
  81. }
  82. private static double Bound(int i){
  83. //计算上界
  84. double cleft = c - cw; //剩余容量
  85. double bound = cp;
  86. //以物品单位重量价值递减序装入物品
  87. while (i <= n && w[i] <= cleft) {
  88. cleft -= w[i];
  89. bound += p[i];
  90. i++;
  91. }
  92. //装满背包
  93. if (i <= n){
  94. double aa = p[i] * cleft;
  95. double bb = w[i];
  96. double temp = aa / bb;
  97. //注意:如果这样写:float temp=p[i] * cleft/w[i];
  98. //则temp计算出来是整数,因为右边是先按整数来算,再将int转float;
  99. bound += temp;
  100. // System.out.println(i);
  101. //System.out.println("界");
  102. //System.out.println(bound);
  103. }
  104. return bound;
  105. }
  106. public static void main(String[] args) {
  107. double p[]={45,25,24};
  108. double w[]={16,15,15};
  109. double c = Knapsack(p,w,30);
  110. System.out.println("0-1背包问题的最优值为:"+c);
  111. }
  112. }

5 结果展示:

五 复杂度分析

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/333013
推荐阅读
相关标签
  

闽ICP备14008679号