回溯算法-01背包问题


1、问题描述

给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包容量为c。问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或不装入背包。不能将物品i装入背包多次,也不能只装入部分的物品i。因此,该问题称为0-1背包问题。

2、算法分析

0-1背包问题是子集选取问题。一般情况下,0-1背包问题是NP难的。0-1背包问题的解空间可用子集树表示。在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入左子树。当右子树中有可能包含最优解时才进入右子树搜索。否则将右子树剪去。

3、算法实现

   1: public class BT_Knapsack01 {
   2:  
   3: int[] weight;
   4: int[] value;
   5: int max; // 背包的最大承重量
   6:  
   7: int n; // 
   8: int[] selection; // 背包选择序列
   9:  
  10: int c_weight; // 当前背包重量
  11: int c_value; // 当前背包价值
  12:  
  13: int bestv; // 最优的背包价值
  14: int[] best_selection; // 最优背包选择序列
  15:  
  16: public BT_Knapsack01() {
  17:     weight = new int[] { 16, 15, 15 };
  18:     value = new int[] { 45, 25, 25 };
  19:     max = 30;
  20:  
  21:     n = weight.length;
  22:     selection = new int[n];
  23:     best_selection = new int[n];
  24:  
  25:     c_weight = 0;
  26:     c_value = 0;
  27:     bestv = 0;
  28: }
  29:  
  30: private void backtrack(int t) {
  31:     if (t >= n) {
  32:         // 限界函数:剪去那些可行,但不可能是最优解的树枝
  33:         if (c_value > bestv) {
  34:             bestv = c_value;
  35:             // 保存最优的selection值:与动态优化的区别,因为selection会在不同的剪枝过程中发生变化
  36:             for (int i = 0; i < n; i++) {
  37:                 best_selection[i] = selection[i]; // 把最优的选择序列保存在best_selection中
  38:                 // System.out.print(selection[i] + " ");
  39:             }
  40:         }
  41:     }
  42:  
  43:     else {
  44:         // 搜索左子树
  45:         if (c_weight + weight[t] <= max) {
  46:             c_weight += weight[t];
  47:             c_value += value[t];
  48:  
  49:             selection[t] = 1;
  50:             backtrack(t + 1);
  51:  
  52:             // 背包当前价值和重量还原,遍历右子树
  53:             c_weight -= weight[t];
  54:             c_value -= value[t];
  55:         }
  56:  
  57:         selection[t] = 0;
  58:         backtrack(t + 1); // 搜索右子树
  59:  
  60:     }
  61: }
  62:  
  63: /**
  64:  * @param args
  65:  */
  66: public static void main(String[] args) {
  67:     // TODO Auto-generated method stub
  68:     BT_Knapsack01 knap = new BT_Knapsack01();
  69:     knap.backtrack(0);
  70:  
  71:    int len = knap.n;
  72:    System.out.println("回溯法背包的最优值为:" + knap.bestv);
  73:     System.out.println("回溯对应的value值分别为:");
  74:     for (int i = 0; i < len; i++) {
  75:         if (knap.best_selection[i] == 1)
  76:             System.out.print(knap.value[i] + " ");
  77:     }
  78:     System.out.println();
  79:     System.out.println("回溯对应的weight值分别为:");
  80:     for (int i = 0; i < len; i++) {
  81:         if (knap.best_selection[i] == 1)
  82:             System.out.print(knap.weight[i] + " ");
  83:     }
  84: }
  85:  
  86: }

最后附一篇利用GA解决01背包问题的文章。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM