经典DP:01背包

背包容量为c,有n件物品,每件物品的价值为v,要求装入的物品总量在不超过背包容量的情况下价值最大。

输入格式

第一行就给出背包容量c,物品数量n

接下来给出n件物品的重量和价值,以空格隔开

输出

最大价值

思路:

经典DP题,这里采用二维DP,横坐标i表示当前考虑的物品号,纵坐标j表示总容量,所以我们建立一个 n 行 c+1 列的二维数组 vector<vector<int>> memo(n, vector<int>(c + 1, -1)) ,这个数组名称为memo。

然后就考虑状态方程,有两种策略,一种是不考虑当前物品,就直接 memo[i][j] = memo[i-1][j] ,另一种是考虑当前物品 memo[i][j] = max(memo[i-1][j],v[i]+memo[i-1][j-w[i]]) ,即把上一次的装填直接转移与如果加当前物品做比较。

假如我们背包容量设置为5,物品个数为3,且三种物品信息如下

id 0 1 2

weight

1 2 3
value 6 10 12

所以我们根据状态转移得到一个二维数组:

物品id/容量 0 1 2 3 4 5
0 0 6 6 6 6 6
1 0 6 10 16 16 16
2 0 6 10 16 18 22

所以我们最后取得的最大价值就是22。

代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     int c, n;
10 
11     cin >> c >> n;
12     if (n == 0)
13         return 0;
14     vector<int> w(n);
15     vector<int> v(n);
16     for (int i = 0; i < n; i++)
17     {
18         cin >> w[i] >> v[i];
19     }
20 
21     vector<vector<int>> memo(n, vector<int>(c + 1, -1));
22 
23     for (int j = 0; j <= c; j++)
24     {
25         memo[0][j] = (j >= w[0] ? v[0] : 0);  //如果当前背包可以放得下就是v[0]否则就是0
26     }
27     
28     for (int i = 1; i < n; i++)
29     {
30         for (int j = 0; j <= c; j++)
31         {
32             memo[i][j] = memo[i-1][j]; //第一种策略就是直接不管当前物品
33             if (j >= w[i]) //第二种策略需要先判断当前容量是否放得下当前物品
34             {
35                 memo[i][j] = max(memo[i][j],v[i]+memo[i-1][j-w[i]]);
36             }
37         }
38     }
39 
40     cout << memo[n-1][c];
41     return 0;
42 }

猜你喜欢

转载自www.cnblogs.com/ZhengLijie/p/12732603.html
今日推荐