DP查缺补漏之多重背包优化原理
DP查缺补漏之多重背包优化原理
普通思路
-
类似完全背包
-
for (int i = 1; i <= n; i++) { for (int j = 1; j <= W; j++) { for (int k = 0; k * w[i] <= j && k <= m[i]; k++) { F[i][j] = max(F[i][j], F[i - 1][j - k * w[i]] + k * v[i]); } } }
-
这里注意\(j\)一定要从\(1\)开始枚举,如果 从\(w[i]\)开始则无法更新小于\(w[i]\)时的\(F[i-1][j]\)。
- 而为滚动数组时,若小于\(j <= w[i]\)能自动使用上一次的\(F[j]\),所以\(j\)才能从\(w[i]\)开始枚举
二进制拆分优化
原理
任何数都能用二进制表示,任何正整数都能由若干个不同的\(2^n\)相加得到。
做法
直接把多重背包每一个物品的总数量用二进制预处理成几个大物品。
然后直接用物品跑01背包即可
代码
for (int i = 1; i <= n; i++)
{
cin >> a >> b >> c;
int bin = 1;
while(bin <= c)
{
v[++cnt] = bin * a;
w[cnt] = bin * b;
c -= bin;
bin <<= 1;
}
if (c)
{
v[++cnt] = c * a;
w[cnt] = c * b;
}
}