AcWing 5. 【曲线救国优化思想】多重背包问题 II
原题链接
中等
作者:
xyAC
,
2024-12-03 17:01:34
,
所有人可见
,
阅读 4
/**
* 我对于这道题的理解: 这觉得这种方法也是 曲线救国
*
* 首先来说这个曲线操作,那在本题中对应的就是拆分的操作;
* 题中的数据范围是比较大的,如果直接遍历来求会超时,那么优化凡是就是将这个多个物品给优化掉,那就利用到了
* 二进制优化
* 对于当前物品的数量一定可以通过若干个数来组成,那么前面几个数可以通过以 2 为底的倍增思想来构造,
* 来看例子:
* 0~1:1
* 0~3: 1 2
* 0~7: 1 2 4
* 0~10:1 2 4 3
*
* 由上面例子来看,前面的范围内的数都可以由后面几个数中构造出来,所以说,以物品数量为范围最大值也同样可以这样
* 构造。
*
* 通过将所有的物品数量都分解完之后,就构成了若干个数量为 1 的物品,这不就转化成了 01 背包了嘛
*
* 女少口马? hhh
**/
#include <iostream>
using namespace std;
const int N = 2010,M = 12010;
int n,m;
int V[M],W[M],f[N];
int main() {
int cnt = 0;
cin>>n>>m;
for(int i = 1;i <= n;i++) {
int a,b,s;
int k = 1;
cin>>a>>b>>s;
while(k <= s) {
cnt ++;
V[cnt] = a*k;
W[cnt] = b*k;
s -= k;
k *= 2;
}
if(s > 0) {
cnt ++;
V[cnt] = a*s;
W[cnt] = b*s;
}
}
n = cnt;
for(int i = 1;i <= n;i++) {
for(int j = m;j >= V[i];j--) {
f[j] = max(f[j],f[j-V[i]] + W[i]);
}
}
cout<<f[m];
return 0;
}