动态规划法解0-1背包问题
问题描述:
有n个背包,重量依次为w1,w2, ... ,wn, 价值依次是v1,v2, ... ,vn, 现在有一个大背包,其容量是capacity,往其中装小背包,要求得到的总价值最大,如何装?
用value[i, w]表示有i个背包且总重量最大是w时的价值,那么当考虑第i个背包时,有两种情况
1. 将此背包装入大包,价值是 v[i] + value[i - 1, w- wi]
2. 此背包不装入打包,价值是 value[i - 1, w]
取两者中的最大值即可
代码如下:
Code
1 class Knapsack
2 {
3 /// <summary>
4 /// 0-1 Knapsack problem solution
5 /// </summary>
6 /// <param name="w">the weight array</param>
7 /// <param name="v">the value array</param>
8 /// <param name="capacity">the total weight that allowed</param>
9 /// Note: w and v must have the same length
10 /// let v[i,w] represents for the max value of the first i knapsack with the capacity of w
11 public void Knapsack01(int[] w, int[] v, int capacity)
12 {
13 int r = v.Length + 1;
14 int c = r;
15
16 int[,] vt = new int[r, c]; // value table
17 bool[,] st = new bool[r, c]; // selected table
18 bool[] res = new bool[w.Length];
19
20 // initialization
21 for (int i = 0; i < r; i++)
22 {
23 vt[i, 0] = 0; // the value with a capacity of 0 is 0
24 vt[0,i] = 0; // the value of 0 knapsack is 0
25 }
26
27 // note the index i and j start from 1
28 // so you can see w[i - 1] below in order to start from 0 for array w
29 for (int i = 1; i < r; i++)
30 {
31 for (int j = 1; j <= capacity; j++)
32 {
33 int unselValue = vt[i - 1, j]; // unselected current knapsack
34
35 if (j >= w[i - 1])
36 {
37 int selValue = v[i - 1] + vt[i - 1, j - w[i - 1]];
38 if (selValue >= unselValue)
39 {
40 vt[i, j] = selValue;
41 st[i, j] = true;
42 if(selValue > unselValue)
43 res[i - 1] = true;
44 continue;
45 }
46 }
47
48 vt[i, j] = unselValue;
49 st[i, j] = false;
50 }
51 }
52
53 // Output the element in array w being selected
54 //for (int i = r - 1; i >= 0&& capacity >= 0; i--)
55 //{
56 // if (st[i, capacity] == true)
57 // {
58 // Console.WriteLine(w[i - 1]);
59 // capacity -= w[i - 1];
60 // }
61 //}
62
63 for(int i = res.Length - 1; i >= 0; i--)
64 if(res[i] == true)
65 Console.WriteLine(i);
66 }
67 }
68