背包容量为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 }