关于双端队列优化多重背包问题的学习笔记

来源:互联网 发布:盛世协同 软件 编辑:程序博客网 时间:2024/06/14 11:34

Problem:有n种物品,它们的重量和价值分别是wi和vi。现在要从中选出一些物品使得总重量不超过W,并且价值的和最大。第i种物品最多取mi个。



暴力算法分析:三重循环枚举物品,背包容量,物品个数。效率为O(nW∑mi)


组合数优化:如果用1,2.....2^k的组合来表示0到0~2^(k+1)-1的所有整数的话。


可以在O(nW∑ log2(mi))的效率内解决问题。


双端队列优化: 可以在O(nW)的时间复杂度内实现。


dp[i][j]:到第i个物品为止总重量不超过j的所有选法中最大的可能价值。


dp[i+1][j]=max{dp[i][j-k*w[i]]+k*v[i]|0<=k<=mi且j-k*w[i]>=0}



在这个方程的转移中,j mod w[i]的值不同则之间的不存在转移关系。


我们首先考虑一下 j mod w[i]=0的情况


定义 a[j]=dp[i][j*w[i]]


那么转移方程就可以改写为dp[i+1][j+k*w[i]]=max(a[j]+k*v[i],a[j+1]+(k-1)*v[i],....a[j+l]);


这样的数列还不能方便的计算


如果令b[j]=a[j]-j*v[i]  


那么 dp[i+1][(j+k)*w[i]]=max{b[j],b[j+1],....b[j+k]}+(j+k)*v[i];

b[j]这个数列就可以用滑动最小值的方法去维护了。







原创粉丝点击