一、01背包
1.01背包模型
有一个体积为V的背包,商店有n个物品,每个物品有一价值v和体积w,每个物品只能被拿一次,问能够装下物品的最大价值。
这里每一种物品只有两种状态即“拿“或“不拿”。
设状态dp[i][j]表示到第i个物品为止,拿的物品总体积为j的情况下的最大价值。
我们并不关心某个物品有没有被拿,只关心当前体积下的最大价值。
转移方程为:
dp[i][j]= max(dp[i-1][j],dp[i-1][j-w]+v);
如果不拿物品i,那么最大价值就是dp[i-1][j],如果拿了就是从体积j-v转移过来,体积会变大w,价值增加V。
最后输出dp[n][V]。
2.优化(听不懂)
二、完全背包
完全背包也叫无穷背包,即每种物品有无数个的背包。
有一个体积为V的背包,商店有n个物品,每个物品有一个价值v和体积w,每个物品有无限多个,可以被拿无穷次,问能够装下物品的最大价值。
这里每一种物品只有无穷种状态即“拿0个、1个、2个··无穷多个”。
设状态dp[i]表示拿的物品总体积为i的情况下的最大价值。
我们并不关心某个物品拿了几个,只关心当前体积下的最大价值。
转移方程为:dp[i]=max(dp[i],dp[i-w]+v),现在就必须使用“新数据”来更新“新数据",因为新数据中包括了拿当前这个物品的状态,而当前这个物品是可以被拿无数次的。
最后输出dp[V]即可。
三、多重背包
1.多重背包基础模型
有一个体积为V的背包,商店有n种物品,每种物品有一个价值v和体积w,每种物品有s个,问能够装下物品的最大价值。
这里每一种物品只有s+1种状态即“拿0个、1个、2个...s个"。
在基础版模型中,多重背包就是将每种物品的s个摊开,变为s种相同的物品,从而退化成01背包处理。
只需要在01背包的基础上稍加改动,对每一个物品循环更新s次即可。
2.二进制优化模型
多重背包基础模型的时间复杂度为O(n*s*V),当s较大时,容易超时。
为了解决这个问题,我们可以在“拆分”操作时进行一些优化,我们不再是拆分成均为1个物品组,而是每一组的物品个数为1、2、4、8 ··· x 最后剩下的单独为一组,这样一定存在种方案来表示0~s的所有情况 (想象二进制数的表示方法)
在经典模型中,一种物品将被拆分为s组,每组一个,而二进制优化模型中,一种物品将被拆分为约log2(s)组,其中每组个数为1,2,4,8··· 例如s=11,将被拆为s=1+2+4+4。
这样对拆分后的物品跑一遍01背包即可,时间复杂度为O(n*log(s)*V)。