二进制优化
在dp中,以多重背包为例:
- 物品有 体积(v),价值(w),数量(s)三个属性
当每一个物品dp时会在原有dp上根据数量(s)判断s倍次,而造成大量重复dp.
二进制分堆:
- 就比如有数量为35的一组v,w相同的物品,就以
(1+2+4+8+16+4)=(2^0)+(2^1)+(2^2)+(2^3)+(2^4)+(2^5)+剩余(4)=35
分为堆 - 将这s个相同物品根据二进制分堆后(注意分堆后剩余的数量也算一堆),在进行dp,虽然依然在重复dp,但dp次数会进行log(n)的优化(这里的log都是以2为底)
为什么会说依然在重复dp:
- 因为分堆后,表面上分了堆之后的每个堆相当于不同的物品了,但因为每一个分堆后的物品的v和w都是相当于 (原物品)*(倍数) 后的加倍原物品,在dp时会以相同倍数体积回溯判断
- 更直白就是 有(1~10)这10个数,要不能重复组装得到
9这个数
原:1+8,1+2+6,1+3+5,2+7,3+6,4+5,9
二进制后:有1,2,4,8,2(剩余)这几个数
现:1+8,1+2+2+4
为什么能用二进制:
-
首先要知道的是每次dp数据迁移都是依赖于上一个的数据进行回溯判断
比如dp[v]=max(dp[v],dp[v-k]+value[k])
在不优化的前提下将每个物品分为1,2,...,s-1,s一共s堆进行dp,其实就相当于枚举了该物品会被选多少个的所有可能性 -
利用二进制把物品分为了
2^0,2^1,....,2^log(s-1),2^log(s)一共logs堆,这log(s)堆并没有枚举所有可能,但在每次dp回溯时,其实就已经枚举了所有堆
例如:s=10; 在没有优化分堆时就有10堆:1,2,3,4,5,6,7,8,9,10
在二进制优化分堆后:1,2,4,8,2(剩余堆)
1=12=23=1+24=45=1+46=2+47=1+6都可以被二进制所表示

浙公网安备 33010602011771号