01背包问题

01背包问题

二维状态方程-代码思路:

struct something{
	int index;//物体编号
	int m;//物体体积
	int v;//物体价值
}

struct bag{
	int count;//存放了前count件物品
	int volume;//背包体积
}
something a[n+1];//n个物品
int f[n+1][bag.volume+1];//存放状态转移方程,初始化为0

for(int i = 1; i < n; ++i){
	for(int j = 1; j < bag.volume; ++j){
		if(j < a[n].m)
			f[i][j]=f[i-1][j];
		else
			f[i][j] = max(f[i-1][j], f[i-1][j-a[n].m]+a[n].v);
	}
}
return f[n][bag_volume];
	

动态规划:

  • 装不下,不装
  • 装得下,判断要不要装

f[n][bag_volume]代表:在背包体积为bag_volume的情况下去装前n个物品,最大价值。

动态规划方程:

d p [ i n d e x ] [ v o l u m e ] = { d p [ i n d e x − 1 ] [ v o l u m e ] v o l u m e < m ( 装 不 下 ) max ⁡ ( d p [ i n d e x − 1 ] [ v o l u m e ] , d p [ i n d e x − 1 ] [ v o l u m e − m ] + v ) v o l u m e ≥ m ( 装 得 下 , 要 不 要 装 ) dp[index][volume] = \begin{cases} dp[index-1][volume] & volume < m (装不下)\\ \max(dp[index-1][volume], dp[index-1][volume-m]+v ) & volume \geq m(装得下,要不要装) \end{cases} dp[index][volume]={dp[index1][volume]max(dp[index1][volume],dp[index1][volumem]+v)volume<m()volumem()

前面的动态规划使用的是二维数组存放状态,可求任意状态的最大价值。

如果只关心背包放前n个(即全部)的话,可优化为使用一维数组。

d p [ v o l u m n ] = { d p [ v o l u m n ] max ⁡ ( d p [ v o l u m n ] , d p [ v o l u m n − m ] + v ) dp[volumn] = \begin{cases} dp[volumn]\\ \max(dp[volumn],dp[volumn-m]+v) \end{cases} dp[volumn]={dp[volumn]max(dp[volumn],dp[volumnm]+v)

根据二维的状态转移方程可得知,dp[index][volumn]的更新依赖到dp[index-1][volumn],一维数组中的dp[volumn]实际等价于二维数组的dp[index][volumn],所以优化成一维时需要使用逆序,避免dp[volumn]被依赖时是dp[index-1][volumn]

由于使用了一维数组,第二层for循环改为从bag.volumn开始逆序,则此时循环判断条件可以改为j>=a[n].m

循环条件更改了,则可以边输入边处理而省略存储过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

modao233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值