思路:用cnt-1个二进制数和一个常数c去凑s,(原本s的时间复杂度就变成了logs)将s分为cnt份,每次计算一份的背包问题,最后每份都整理好之后,按照优化01背包进行计算
#include<iostream>
using namespace std;
const int N = 25000, M = 1010;
int n, m , s;
int v[N], w[N];
int f[N];
int main()
{
cin>>n>>m;
int cnt = 0;
while(n -- ){
int a, b, s;
cin>>a>>b>>s;
int k = 1;
while(k <= s){
cnt ++ ;//此时的cnt代表2的次数
v[cnt] = a * k;
w[cnt] = b * k;
s -= k;//不断将s拆分为二进制数的和
k *= 2;
}
if(s){
//此时s剩下的部分就是常数c
cnt ++ ;
v[cnt] = s * a;
w[cnt] = s * b;
}
}
n = cnt;//总共将s分为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]<<endl;
return 0;
}