dp解决01背包问题


前引

博主现在在面临着七门考试,但今晚得补一个算法作业,在此记录一下解决思路。


一.问题描述

有 N 件物品和一个最多能被重量为 W 的背包。第 i 件物品的重量是 weight[i],得到的价值是 value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
这里我们把问题具体化:有四件商品,价值依次为 1500,2000,2000,3000,对应的重要依次为1,1,3,4,背包容量为4.


二.解决思路

动态规划: 先解决子问题,再逐步解决大问题
我们的目标是求出在有四件商品可选的情况下,容量为4的背包能装入的最大价值。那么这个问题的子问题是:在有1~4个商品可选的情况下,容量1 ~ 4的背包能装入的最大价值。我们可以表示为以下表格

容量1容量2容量3容量4
(1500,1)1500150015001500
(2000,1)2000350035003500
(2000,3)2000350035004000
(3000,4)2000350035004000

显然表格右下角的数值就是我们最终的答案

按照先遍历物品,再遍历背包重量的思路,具体的求解思路应该是:先求出一件商品可选情况下,背包总 1 ~ 4的最大价值,再求出二件商品可选…逐步求出四件商品可选时,背包容量为4的最大价值


三.为什么先解决子问题可以最后解决大问题?

对于表格的每一项,在第一行仅可选一件商品情况下,背包价值在能装下该商品的情况下,最大价值为该商品价值

if (i == 0 && weight[0]<=j) // i:commodity serial number , j:bagweight
		dp[i][j] = value[0];  // Only one item can be selected

对于表格的其余项,填入的值只有两种选择

  1. 当前商品行的价值 + 背包剩余容量可装下的最大价值

  2. 不选择装入当前行商品,背包内物品最大价值不变

两者取max
显然,当背包容量小于当前商品重量时,必然只能选择第二个

for (int i = 1; i < cdyNum; i++)  // commodity serial number
		for (int j = 1; j <= bagWeight; j++)  // bagweight
		{
			if (j < weight[i])//bagWeight is less than the current row weight, the maximum value will not change
				dp[i][j] = dp[i - 1][j]; 
			else
				dp[i][j] = max(dp[i - 1][j], value[i] + dp[i - 1][j - weight[i]]);
		}

自此我们可以看出,子问题为我们提供了一个信息:背包剩余容量可装下的最大价值,进而我们才可以确定两个选择的值,进而选出最大价值。


四. C++

代码中对表格的初始化略显多余,对除第1行第0列的赋值以外均没有必要,但为了避免变量出现不确定值,我还是选择对该部分初始化为0。

void Solution()
{
	int bagWeight = 4;
	int cdyNum = weight.size(); //number of commondity 
	vector<int>weight { 1,1,3,4};
	vector<int>value{ 1500,2000,2000,3000};


	vector<vector<int>> dp(cdyNum,vector<int>(bagWeight + 1));// Two-dimensional array

	//initial
	for(int i = 0;i<cdyNum;i++)  // commodity serial number
		for (int j = 0; j <= bagWeight; j++)  // bagweight
		{
			if (j == 0)  // bagWeight = 0 ,so total value = 0
				dp[i][j] = 0;
			else if (i == 0 && weight[0]<=j)
				dp[i][j] = value[0];  // Only one item can be selected
			else 
				dp[i][j] = 0;
		}

	// dynamic programming
	for (int i = 1; i < cdyNum; i++)  // commodity serial number
		for (int j = 1; j <= bagWeight; j++)  // bagweight
		{
			if (j < weight[i])//bagWeight is less than the current row weight, the maximum value will not change
				dp[i][j] = dp[i - 1][j]; 
			else
				dp[i][j] = max(dp[i - 1][j], value[i] + dp[i - 1][j - weight[i]]);
			
		}

	//result
	cout <<"the maximum value: "<< dp[cdyNum - 1][bagWeight] << endl;
}


int main()
{
	Solution();
}

咱就把 01 背包问题讲个通透! - 力扣

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值