状态 &转移
状态:
f(i,C)
表示考虑将[0..i]的背包放入容量为C的背包的最大价值
状态转移:
f(i,C)=max{f(i−1,C),v[i]+f(i−1,C)}
解题代码
class Solution {
private:
vector<vector<int>> memo;
// [0..index] 放进容量为C的背包的最大价值
int maxValue(const vector<int> &w, const vector<int> &v, int index, int C){
if (index < 0 || C <= 0)return 0;
if (memo[index][C] != -1)return memo[index][C];
memo[index][C] = max(maxValue(w, v, index - 1, C),
w[index] <= C ?
v[index] + maxValue(w, v, index - 1, C - w[index]) :
0);
return memo[index][C];
}
public:
// 动态规划 (优化,只用一维数组存储)
int knapsack2(const vector<int> &w, const vector<int> &v, int C){
int n = w.size();
if (n == 0)return 0;
// memo[i][j] : 考虑将[0..i]物品放进容积为j的背包最大价值
vector<int> memo(C + 1, -1);
// 对基础问题进行设置,对[0,0]物品进行考虑,分别放进容量为[0..C]的背包的最大价值
for (int j = 0; j <= C; j++)
memo[j] = (j >= w[0] ? v[0] : 0);
for (int i = 1; i < n; i++){
for (int j = C; j >= w[i]; j--)
memo[j] = max(memo[j], j >= w[i] ? v[i] + memo[j - w[i]] : 0);
}
return memo[C];
}
// 动态规划
int knapsack1(const vector<int> &w, const vector<int> &v, int C){
int n = w.size();
if (n == 0)return 0;
// memo[i][j] : 考虑将[0..i]物品放进容积为j的背包最大价值
memo = vector<vector<int>>(n, vector<int>(C + 1, -1));
// 对基础问题进行设置,对[0,0]物品进行考虑,分别放进容量为[0..C]的背包的最大价值
for (int j = 0; j <= C; j++)
memo[0][j] = (j >= w[0] ? v[0] : 0);
for (int i = 1; i < n; i++){
for (int j = 0; j <= C; j++)
memo[i][j] = max(memo[i - 1][j], j >= w[i] ? v[i] + memo[i - 1][j - w[i]] : 0);
}
return memo[n-1][C];
}
int knapsack(const vector<int> &w, const vector<int> &v, int C){
int n = w.size();
memo = vector<vector<int>>(n, vector<int>(C + 1, -1));
return maxValue(w, v, n - 1, C);
}
// 测试
void test(){
int weight[] = { 1, 2, 3 };
int value[] = { 6, 10, 12 };
vector<int> w(weight, weight + 3), v(value, value+3);
cout << knapsack(w, v, 5) << endl;
}
};