时隔多年,重拾背包dp,简单的看了看01背包,完全背包和多重背包。在航电上随便看了一题多重背包竟然WA了一发。
仔细的整理了一下,然后发现多重背包实际上就是01背包。
首先说一下01背包和多重背包的区别和相似点:
人拥有的购买力是一定的,每个物品的价格和价值是固定的,这是简单背包问题的共性暂且不说。最重要的一点是,01背包问题和多重背包问题的物品的数量都是有限的(01背包每件物品只有一个,而多重背包的物品数量为有限个);而这种特性决定了多重背包本质上就是01背包,如若将多重背包中的每一个物品当成不同的物品(即使他们的价格和价值是相同的),那么这样的每一件物品仍然可以看作每一件物品只有一个,有取和不取两个选择。就是一个裸的01背包题目了。当问到最优情况下,每种物品分别取多少的时候也是可以很简单在此基础上做到的。
因此,多重背包的种类×数量二维就可以当作01背包的物品种类这一维,当我们dp的时候,01背包如果使用降低空间复杂度的做法,也就是将dp[w]简化为dp[w]时,因为此时的dp[w](dp[w])需要由dp[w-w]推算得到。从前推dp[w]会导致dp[w-w]的值由dp[w-w]覆盖,从而得到错误的结果。由于多重背包和01背包的本质相同,所以多重背包的dp[w]也须从后往前推得。
明白了这一点,三种简单背包:01背包,完全背包和多重背包的dp递推方法就显而易见了。
值得说的是,通过这种拆分的思想,可以减少一部分时间复杂度的。
不过在拆的时候不能将Cn拆成1+1+1+1+1+1.....+1的形式。这么做会超时。应该将Cn拆成 Cn=1+2+4+8+...+(Cn-sum)。 这里sum表示前面的数字之和,例如 按照规律加到第m个数,发现已经大于Cn,那么sum就表示从 1+2+4+8+.....+ 2^(m-2)。
我们可以检验,在[1,Cn]中任意的数 我们都可以在这个序列中找到若干数相加得到。
拆分结束后我们就可以按照01背包求解。 dp[j]=max(dp[j],dp[j-cos[i]]+val[i]) 。
时间复杂度为 O(W*sigma(logCi))