一、0-1 背包
题目解析
有一个背包,最多能容纳的体积是 V,有 n 个物品,体积为 v[i],价值 w[i]。
- 问 1:最多能装的最大价值的物品?(背包不必装满)
- 问 2:背包恰好装满,最多能装多大价值的物品
算法原理
第一问
-
状态表示
- dp[i][j]:从前 i 个物品中挑选,总体积不超过 j,所有选法中能挑选出来的最大价值。
-
状态转移方程
- 不选 i 物品:dp[i-1][j]
- 选 i 物品:w[i] + dp[i-1][j-v[i]] (需满足 j >= v[i])
- 综合:
dp[i][j] = max(dp[i-1][j], w[i] + dp[i-1][j-v[i]])
-
初始化
- 容量不超过 0 或物品为 0 时,价值为 0。
-
填表顺序
- 从上往下,从左往右。
-
返回值
dp[n][v]
第二问(恰好装满)
- 状态表示
- dp[i][j]:从前 i 个物品中挑选,总体积等于 j,所有选法中能挑选出来的最大价值。
- 状态转移方程
- 需判断
dp[i-1][j-v[i]] != -1。
- 需判断
- 初始化
dp[0][0] = 0,其余dp[0][j] = -1。
代码编写
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, v;
cin >> n >> v;
vector<int> vl(n + 1), wl(n + 1);
vector<vector<int>> (n + , <>(v + ));
vector<vector<>> (n + , <>(v + ));
( i = ; i <= n; i++) {
tv, tw;
cin >> tv >> tw;
vl[i] = tv;
wl[i] = tw;
}
( i = ; i <= v; i++) dp2[][i] = ;
( i = ; i <= n; i++) {
( j = ; j <= v; j++) {
(j - vl[i] >= )
dp1[i][j] = (dp1[i - ][j], wl[i] + dp1[i - ][j - vl[i]]);
dp1[i][j] = dp1[i - ][j];
(j - vl[i] >= && dp2[i - ][j - vl[i]] != )
dp2[i][j] = (dp2[i - ][j], wl[i] + dp2[i - ][j - vl[i]]);
dp2[i][j] = dp2[i - ][j];
}
}
cout << dp1[n][v] << endl;
(dp2[n][v] == ) cout << ;
cout << dp2[n][v];
;
}


