前置知识
01背包 和 完全背包 喵!
概念:什么是多重背包
相较于01背包和完全背包,更实际的,多重背包是每一个物品有个数限制的背包,这相较于前面两个就有一点点难度了
思路:设计多重背包
首先,最最最基础的,我们可以像完全背包那样,暴力枚举每一个物品选多少次,代码时间复杂度是三次方的。
1 2 3 4
| for(int i = 1; i <= n; i++) for(int j = 0; j <= v; j++) for(int k = 0; k <= s[i] && k * c[i] <= j; k++) dp[i][j] = max(dp[i][j], dp[i - 1][j - k * c[i]] + k * w[i]);
|
那么,我们考虑更优的方式去选择物品。
当你面对一些奇奇怪怪的优化分组没有思路的时候,你就可以稍微考虑考虑二进制。二进制拆分,因为二进制转变为十进制的唯一性,所以我们对于物品数量二进制拆分可以优化到 $O(n\log n)$ ,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| for(int i = 1; i <= n; i++) { int a, b, s; scanf("%d%d%d", &a, &b, &s); int k = 1; while(k <= s) { cnt++; c[cnt] = k * a; w[cnt] = k * b; s -= k; k *= 2; } if(s > 0) { cnt++; c[cnt] = a * s; w[cnt] = b * s; } }
for(int i = 1; i <= cnt; i++) for(int j=v; j >= c[i]; j--) dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
|
实践:经典例题分析