动态规划-背包问题(2)


  二三分都讲完了,我还在磨背包问题,貌似磨着磨着脸皮就厚了。记得以前还不懂一个不在同一专业的高中同学为什么能做到那么懒,以至于最后复习阶段每一科都在担心着会挂科,现在看来我理解了。开学的消息有眉目了,不过最早也得五月十五以后。说实话开学以后我还怎么看回放啊!
  还是继续背包问题。
  (3)多重背包
  一般形式:
  在这里插入图片描述
  变化很清晰,和完全背包相比每种物品的数量不再是无限了,而是有限个数的。不过要分析多重背包问题如何处理,就需要分析一下多重背包与完全背包的变化到底在哪。原先第i种物品无数件,所以每次判断某一种物品时都可以一直枚举直到再加一件第i种物品时就会超出背包容量限制为止,而现在这种物品不再是无限件的了,而是有限件,那么就有两种情况,当这第i种物品全部放入背包时背包有可能会装满(当然不一定需要全放入才能装满,但只要部分可以装满,全部的自然能够让它装满),还有可能装不满。如果这种物品能够将其装满,那么和完全背包没差了,取多少件也无所谓反正不超过背包容量条件下取多少件都没问题。但如果装不满,这种物品取用的限制就不再是背包容量了,而是物品的个数。所以综合来看,完全背包在取用第i件物品时的限制条件是背包容量,而多重背包的限制条件是背包容量和此种物品个数,这样这个问题就解决了。甚至于状态转移方程都一样(当然,对应某个截止条件不同)。
  不过,在处理这一问题时还发现这一问题适合用二进制的方法进行优化。二进制优化原理就是利用所有的数都可以用一个或几个2的幂的数来表示(或者说其实就是每个十进制数都可以表示成二进制数的形式)。如此,利用这一特点可以只计算2的幂个这一种物品的情况而其它个数时都去用这些个数去组成,从而大大节省了时间复杂度。但再考虑下,为什么这个问题能够用这一方法进行优化?其实就是因为“种”这个字眼,因为同一种物品都是完全一样的,而一件件的往背包内放其实就是简单的累加,就是加入一件这种物品效果的累加,所以每次放入的一件可以看作是一样的。既然能够二进制优化,自然可以做到八进制优化或者十进制,十六进制吧,不过那样效率肯定不如二进制的高而且还麻烦。如此看来,既然多重背包能用,完全背包当然也可以,不过01背包就不适合了。二进制优化说起来简单但真正应用起来就不是那么容易了。
  (4)分组背包
  在这里插入图片描述
  忽然变了个感觉,一看到会措手不及。对于有若干组,第k组有两种情况,选还是不选,如果选那么就只能选一件自然选个效果最好的。选组类似01背包,而对于选定的这一组内每个物品都要试一试。而代码形式也很眼熟,即在01背包的基础上在最内层加一个循环,用来一一试一下第k组的每个元素:

for k组
{
	for 容积V~001背包从后往前更新数组元素)
	{
		for d第k组内的第i个元素
		{
			dp[j]=max(dp[j],dp[j-a[i]]+v[i]);
		}
	}
}


  代码实现或许没那么难,但真正遇到问题能够分析出这是分组背包的问题才是关键。不过其实不止这个题,无论遇到哪个题分析出这个问题是那种算法的类型或者适合用哪种算法解决一直都是关键。当然,对于这一类型就不再适用二进制优化了,为啥,不一样呗。
  再回过头来看一下这四种背包问题,看似是问题逐渐变得特殊了,其实仔细琢磨其中的变化后能够发现恰巧相反。最初的01背包才是特殊情况,而每一种算法都是下一种的特例。分组背包有k组,每组都有不同数量个不相同的物品且只能取一个,到了多重背包其实还是有k组,每组(种)的数目不同但都相同且能取任意个(不超了)。但这个问题却可以这么想:每组的数目仍然不同且互不相同,并且只能取一个,只需要做到一点,互不相同的这若干件物品其中第i件的“参数”(就是重量和价值)恰成第一件的i倍。如此从不同的若干件中取出i件其实就是从相同的若干件中取出了i件。而多重背包到完全背包就是这k组(种)每一组(中)的件数是无限件或者说都完全可以仅用这一件物品装满背包,而就相当于这k组中每组中的物品仍然类似多重背包中的情况但(重量)最大的那一件自己就可以装满背包或背包装不下。而到了01背包就更特殊了,直接这k组中的每一组(种)都只有一件物品。如此,其它三种类型背包问题就都可以转化成其之后的背包问题的特例。
  其实这一幕似曾相识。就拿物理为例,我们一开始学的最初的物理就是牛顿力学和另两个名字挺长而且不好记的电磁场及统计力学为代表的经典物理学,在之后各种发现如光速不变原理发现原先的理论都是在低速状态下的特例,如此使得经典物理学更加完善。而科学家们对于微观世界研究出量子物理学又打破这一规则,认为整个原先的认知都只是在宏观状态下的特例。感觉一些白头发卷胡子,长胡子没头发的老大爷们像群孩子似的你争我抢,但探索的却都是震世的真理。不过,这些个特例什么的关系和我们学的这些还是挺像的,不是吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值