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]这个数列就可以用滑动最小值的方法去维护了。