一.01背包
1.01背包模板题
题意:总体积有V,每个物品都有w[i]价值,和v[i]体积,在不超过V时,让总价值最大
解决方案:
状态:dp[i][j]表示1到i物品自由选择,容量不超过j的情况下的最大价值
状态转移:
(1)不要i号物品,dp[i-1][j]
(2)要i号物品,dp[i-1][j-v[i]]+w[i]
上面两个值,二者取大
通过观察状态转移方程,我们发现,每个格子依赖它的上面的格子,和它的上面左边的格子
所以我们的遍历顺序为从上往下,从左往右
初始状态:
根据依赖,我们需要初始化第一行的格子,dp[0][j],那么选择0号物品,即为不选物品(因为物品编号从1开始),那么价值为0,则dp[0][j]=0;
cpp
int f1(vector<int>& w, vector<int>& v,int V,int n) {
vector<vector<int>>dp(n + 1, vector<int>(V + 1, 0));
//初始状态dp[0][j]=0
//dp[i][j]:1-i号物品任意选择,容量不超过j的最大价值
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= V; j++) {
//不要i号物品
dp[i][j] = dp[i - 1][j];
//选择i号物品
if (j - v[i] >= 0) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
}
}
}
return dp[n][V];
}
状态压缩:
由于我们发现,每个格子依赖,上方,和左上方,所以我们只需要从上往下,从右往左更新
cpp
int f2(vector<int>& w, vector<int>& v, int V, int n) {
vector<int>dp(V + 1, 0);
//初始状态dp[0][j]=0
//dp[i][j]:1-i号物品任意选择,容量不超过j的最大价值
for (int i = 1; i <= n; i++) {
for (int j = V; j >=0; j--) {
//不要i号物品
//选择i号物品
if (j - v[i] >= 0) {
dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
}
}
}
return dp[V];
}