0-1背包问题:

n个商品(单个商品不可拆分),放入容量为 V 的购物车,如何才能让购物车中的商品总价最大?

书中介绍的动态规划解法是设 dp[i][j] 为前 i 号商品在容量为 j 的购物车中的最大价值,并自底向上求解。这种方法比较紧凑,但是不那么自然,难以想到利用商品编号 i 和容量 j 建立动态规划数组。

下面介绍一种思路较为自然直白的方法:

设 dp[i][j] 为第 i 号~第 j 号商品放入容量 V 的购物车所能产生的最大总价。vdp[i][j] 为 dp[i][j] 对应的商品占用购物车的容量。

则有:

1、dp[i][j] = 0 ; i == j && volume_i > V --- 只有一个商品且放不下

2、dp[i][j] = value_i ; i == j && volume_i <= V --- 只有一个商品且能放下

3、dp[i][j] = 0 ; j - 1 == 1 && volume_i > V && volume_j > V 

4、dp[i][j] = value_i  + value_j ;  j - 1 == 1  && volume_i  + volume_j  <= V 

5、dp[i][j] =value_i ;   j - 1 == 1  && volume_i   <= V &&  volume_j   > V

6、dp[i][j] =value_j ;   j - 1 == 1 && volume_i  > V &&  volume_j   <= V

7、dp[i][j] = max(dp[i][k-1] + dp[k+1][j] + 0), i < k < j ;  j - 1 > 1 &&   volume_k > V - (vdp[i][k-1] + vdp[k+1][j])

8、dp[i][j] = max(dp[i][k-1] + dp[k+1][j] + value_k), i < k < j ;  j - 1 > 1 &&   volume_k <= V - (vdp[i][k-1] + vdp[k+1][j])

这些情况看起来很复杂,但是我们可以稍作整理:

dp[i][j] = condition(i, V); i == j

dp[i][j] = value_i  + value_j ;  j - 1 == 1  && volume_i  + volume_j  <= V 

dp[i][j] = max(condition(i, V), condition(j, V)) ;   j - 1 == 1  &&  volume_i  + volume_j  > V 

dp[i][j] = max(dp[i][k-1] + dp[k+1][j] + condition(k, V - vdp[i][k-1] - vdp[k+1][j]))

其中

condition(k, vRemain) = 0; volume_k > vRemain

condition(k, vRemain) = value_k; volume_k <= vRemain

至此,已找到递归式,可以自底向上求解,代码如下:

测试用例,对于5个商品,放入容量为10的购物车

价值:6 3 5 4 6

体积:2 5 4 2 3

输出最大价值为17,占用体积为9

 1 #include "iostream"
 2 #include "vector"
 3 #include "algorithm"
 4 
 5 #define SIZE 10
 6 #define INF 65535
 7 
 8 using namespace std;
 9 
10 class Goods
11 {
12 public:
13     Goods(int value, int volume)
14     {
15         this->value = value;
16         this->volume = volume;
17     }
18 public:
19     int value;
20     int volume;
21 };
22 
23 pair<int, int> condition(vector<Goods> &gArr, int k, int vRemain)
24 {
25     if (gArr.at(k).volume > vRemain)
26     {
27         return make_pair(0, 0);
28     }
29     else
30     {
31         return make_pair(gArr.at(k).value, gArr.at(k).volume);
32     }
33 }
34 
35 void package(vector<Goods> &gArr, int volume)
36 {
37     int dp[SIZE][SIZE], vdp[SIZE][SIZE];
38     int size = gArr.size();
39     pair<int, int> result1, result2;
40 
41     for (int begin = 0; begin < size; begin++)
42     {
43         for (int step = 0, i = 0, j = begin; step < size - begin; step++, i++, j++)
44         {
45             if (i == j)
46             {
47                 result1 = condition(gArr, i, volume);
48                 dp[i][j] = result1.first;
49                 vdp[i][j] = result1.second;
50             }
51             else if (abs(i - j) == 1)
52             {
53                 if (gArr.at(i).volume + gArr.at(j).volume <= volume)
54                 {
55                     dp[i][j] = gArr.at(i).value + gArr.at(j).value;
56                     vdp[i][j] = gArr.at(i).volume + gArr.at(j).volume;
57                 }
58                 else
59                 {
60                     result1 = condition(gArr, i, volume);
61                     result2 = condition(gArr, j, volume);
62                     dp[i][j] = result1.first > result2.first ? result1.first : result2.first;
63                     vdp[i][j] = (result1.first == 0 && result2.first == 0) ? 0 :
64                         (result1.first > result2.first ? result1.second : result2.second);
65                 }
66             }
67             else
68             {
69                 for (int k = i + 1; k < j; k++)
70                 {
71                     result1 = condition(gArr, k, volume - (vdp[i][k - 1] + vdp[k + 1][j]));
72                     dp[i][j] = dp[i][k - 1] + dp[k + 1][j] + result1.first;
73                     vdp[i][j] = vdp[i][k - 1] + vdp[k + 1][j] + result1.second;
74                 }
75             }
76         }
77     }
78 
79     cout << dp[0][size - 1] << endl;
80     cout << vdp[0][size - 1] << endl;
81 }
82 
83 
84 void main()
85 {
86     vector<Goods> gArr;
87     int maxVolume = 10;
88 
89     gArr.push_back(Goods(6, 2));
90     gArr.push_back(Goods(3, 5));
91     gArr.push_back(Goods(5, 4));
92     gArr.push_back(Goods(4, 2));
93     gArr.push_back(Goods(6, 3));
94 
95     package(gArr, maxVolume);
96 }

 

posted on 2019-04-14 14:30  SHQHDMR  阅读(222)  评论(0编辑  收藏  举报