背包相关问题总结

至多与恰好

如果问恰好装\(v\),则初始化\(dp[]=-INF,dp[0]=0\)。二维\(dp\)则初始化\(dp[][]=-INF,dp[0][0]=0\)。(这样就能是那些能够恰好装满背包的物品的值为正数,而那些不能恰好装满背包的物品的值就为负数。)

如果问至多装\(v\),则初始化\(dp[]=0\)

一定要注意,要求恰好时,分组背包枚举某一组的元素之前,要再设\(dp[j]=-INF\)。(\(INF\)的值要够小!)

二维\(dp\)时(要求恰好),最开始的\(max\)也可能要设\(-INF\)(除了第一次时)

01背包和完全背包枚举顺序

01背包是倒序,完全背包是顺序。

(若倒序枚举,\(j\)只会一直减小,所以我们总是用第\(i-1\)个阶段向第\(i\)个阶段转移,是01背包。如果是正序,那么\(j\)有可能被\(j-v_i\)更新。\(j\)增大到\(j+v_i\)时,又可能被\(j\)更新。这时两个都处于第\(i\)个阶段的状态之间发生了转移,相当于第\(i\)个物品被使用了两次,是完全背包。)

分组背包枚举顺序

先枚举是哪个组\(i\),再倒序枚举体积\(j\),最后再枚举每组组内元素\(k\)

(注意枚举顺序。\(i\)是阶段,\(i\)\(j\)共同构成状态,而\(k\)是决策。)

多重背包枚举顺序

思想:转化为共有\(\sum\limits_{i=1}^{n}k_i\)个物品的01背包问题(\(k_i\)是每种物品的个数)。

先枚举是哪种物品\(i\),再枚举\(i\)的个数\(j\),最后再倒序枚举体积\(k\),做01背包dp[k] = max(dp[k], dp[k - w[i]] + c[i])

注意res = max{dp[0 ~ v]}

二进制拆分法(优化多重背包)

原来的多重背包时间复杂度是\(O(V\sum\limits_{i=1}^nk_i)\)的,效率较低。

我们可以把数量为\(k_i\)的第\(i\)种物品拆成\(p+2\)个物品(\(p\)是满足\(2^0+2^1+2^2+...+2^p\le{k_i}\)的最大整数)。

它们的体积分别为\(2^0*w_i,2^1*w_i,...,2^p*w_i,r_i*w_i\)\(r_i=k_i-\sum\limits_{i=0}^p2^i\))。

那么这\(p+2\)个物品可以且只能凑成\(0\sim{k_i}*w_i\)之间所有能被\(k_i\)整除的数,这等价于原问题中体积为\(w_i\)的物品可以使用\(0\sim{k_i}\)次。这时的复杂度是\(O(V\sum\limits_{i=1}^nlog(k_i))\)

posted @ 2020-10-26 22:02  andysj  阅读(96)  评论(0编辑  收藏  举报