回溯算法-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