背包问题
背包问题是一类NP完全问题,属于1D/1D动态规划,现总结如下:
一、01背包问题
01背包问题:现有n件物品,第i件物品的价值为v[i],体积为w[i],现有一个能装得下p体积的背包,求该背包所能携带的最大价值。
看到这个问题,我们可以先举个栗子:(图是盗的)
可以发现我们可以建立一个二维表来模拟这个过程。很容易想到的是,如果存在一个背包的容量是p’,另外存在一个物品的重量是w[i],且存在这么一个关系:,那么我们将可以对这个结果进行贪心处理,容易得到下面这个式子:
那么我们再将这个公式推广到从1到p(f[0]=0),就可以得到最优解。推广后的公式(状态转移方程)如下:
注意:在将f数组填表时需要从后往前填,避免将同一件物品重复累加。
时间复杂度:
以上内容已经加了滚动数组优化不再多说(逃
二、完全背包问题
完全背包问题:现有n种物品,第i种物品的价值为v[i],体积为w[i],*每种物品可以选用无限多个*。现有一个能装得下p体积的背包,求该背包所能携带的最大价值。
可以看出完全背包与01背包的区别就在于完全背包每种物品可以选无穷多个。又因为完全背包的容量是有限的,所以我们可以把每一件物品拆分成(n/p)下取整件,那么这个完全背包问题就会被弱化成01背包来解答。但该算法效率低下,时间复杂度只有可怜的,算是一种低能算法了。
那么我们该如何优化呢?背包九讲里有各种玄学优化,这里指阐明最高效的。
前面的注意点写过,在01背包问题中要逆向填写f数组,从而避免重复计算同一件物品。但在完全背包中,我们需要的是什么?正是重复计算同一个物品啊。所以在这里我们只要将f数组顺向填写,就可以完美解决该问题。
时间复杂度与01背包一样
完全背包的状态转移方程其实和01背包一模一样。
三、多重背包问题
多重背包问题:现有n种物品,第i种物品的价值为v[i],体积为w[i],*每种物品可以选用m[i]个*。现有一个能装得下p体积的背包,求该背包所能携带的最大价值。
此类问题限定了每种物品的个数,所以我们可以将其转换为完全背包或01背包解答。朴素算法非常好思考。
①:改一下完全背包的状态转移方程:
②:将这个问题转化为01背包,即将m[i]个物品分开讨论。
上述两种方法时间复杂度都是效率太低,需要优化。
对于第②种方法,我们可以进行优化。我们可以将m[i]个物品拆成1, 2,22,……,2(k-1),m[i]-2^k+1这么多项,即表达成二进制形式,那么我们的复杂度就可以有质的变化,成为
以上即是我对三种背包问题的理解,今后会继续更新。