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背包問題的文章。
