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背包问题的文章。