01背包和完全背包

// 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];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值