// 0-1背包
int maxValue(std::vector<int>& weight, std::vector<int>& value, int bagweight) {
int itemNum = weight.size();
std::vector<std::vector<int>> dp(itemNum, std::vector<int>(bagweight + 1, 0));
// dp[i][j] -> 从 0 ~ i 种选择物品,装在容量为 j 的包里,最大价值是多少?
for (int i = 0; i < itemNum; ++i) {
dp[i][0] = 0; // 背包容量为 0 时,装什么物品都装不下,最大价值均为 0
}
for (int i = 0; i <= bagweight; ++i) {
if (weight[0] <= i) {
dp[0][i] = value[0];
}
}
// 递推公式,如何求 dp[i][j]
// 1. weight[i] > j,背包放不下物品 i,那么dp[i][j] = dp[i - 1][j];
// 2. weight[i] <= j,有两种选择,即放 i 和不放 i,不放 i :最大价值为 dp[i - 1][j]
// 放 i :最大价值为 dp[i - 1][j - weight[i]] + value[i]
// 考虑方式:既然确定要放 i,那么背包容量就减少为 j - weight[i],而放 i 之前只有 0 ~ i - 1
// 所以 dp[i][j] = std::max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])
for (int i = 1; i < itemNum; ++i) {
for (int j = 1; j <= bagweight; ++j) {
if (j < weight[i]) {
dp[i][j] = dp[i - 1][j];
}
else {
dp[i][j] = std::max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
}
for (auto& x : dp) {
for (auto& y : x) {
std::cout << y << " ";
}
std::cout << std::endl;
}
return dp[itemNum - 1][bagweight];
}
int maxValueAnotherWay(std::vector<int>& weight, std::vector<int>& value, int bagweight) {
// 滚动数组解决
int itemNum = weight.size();
std::vector<int> dp(bagweight + 1, 0);
for (int i = 0; i < itemNum; ++i) {
// 要从最后一个位置开始更新状态,从左开始会发生覆盖
for (int j = bagweight; j >= weight[i]; --j) {
// 这里不同修改 j < weight[i] 时的状态
// 是因为 j < weight[i] 时,新一轮的状态就是上一轮的状态
dp[j] = std::max(dp[j], dp[j - weight[i]] + value[i]);
}
}
for (auto& x : dp) {
std::cout << x << " ";
}
return dp[bagweight];
}
int main() {
std::vector<int> weight{ 1,3,4 };
std::vector<int> value{ 15,20,30 };
//maxValue(weight, value, 4);
maxValueAnotherWay(weight, value, 4);
return 0;
}
// 完全背包
int maxValue(std::vector<int>& weight, std::vector<int>& value, int bagSize) {
int itemNum = weight.size();
std::vector<int> dp(bagSize + 1, 0);
// 完全背包即每一件物品可以重复拿取,所以在遍历背包容量时,从小到大遍历
for (int i = 0; i < itemNum; ++i) {
for (int j = weight[i]; j <= bagSize; ++j) {
dp[j] = std::max(dp[j], dp[j - weight[i]] + value[i]);
}
}
return dp[bagSize];
}