本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是算法数据结构专题的第13篇文章,也是动态规划专题的第二篇。
上一讲当中我们一起学习了动态规划算法中的零一背包问题,我们知道了所谓的零一背包是指每一种物品只有一个,所以它的状态只有0和1两种,即拿或者不拿。而今天我们要来讨论物品不止有一个的情况,物品不止有一个也分两种,一种是不作任何限制,要多少有多少,这种称为完全背包问题,另一种是依然有个数限制,这种称为多重背包问题。
我们一个一个来看,我们先从其中比较简单的完全背包开始。由于我们这是一个连续的专题,没有看过上篇文章或者是新关注的同学可以移步我们专题的第一篇:
动态规划入门——经典的完全背包与多重背包问题mp.weixin.qq.com完全背包
在之前的文章当中,我们阐述了动态规划当中状态和决策以及状态转移的相关概念。在背包问题当中,背包的容量是状态,而选择哪个物品进行获取则是决策,当我们制定了一个决策之后,背包会从一个状态转移到另一个状态。而动态规划算法就是枚举所有状态和决策,获得所有的状态转移,并且记录这个过程中每个状态能够获得的最优解。
在之前的文章当中,我们先遍历了所有的决策,然后再枚举了所有的状态,计算在决策下进行转移之后得到的结果。在之前的零一背包问题当中,由于我们每个物品只能获取一个,如果在前面的状态执行了决策,那么后面的状态则不能进行相同的决策。这也就是动态规划的后效性,而在完全背包问题当中,我们去掉了这个限制,也就意味着决策之间不再有后效性,一个决策可以重复应用在各个状态当中。
所以如果你能理解上面这段话,那么整个算法其实非常简单,几乎就是零一背包的代码。只不过我们把其中倒叙遍历的背包状态再”修正“回来。
之前我们为了避免物品的重复获取,所以采用了倒叙遍历的方法,如今我们不再对数量进行限制,意味着我们可以自由地采取决策进行转移。要做到这点,就是单纯的两重循环,第一种枚举决策, 第二重枚举状态,记录所有转移可能带来的最优解即可。我们来看代码:
dp = [0 for _ in range(1