多重背包二进制优化
将(num)件,价值(v),花费(cost)的物品((v,w))拆分为((v,w),(v imes 2^1,w imes 2^1),(v imes 2^2,w imes 2^2),cdots,(x,y))(其中((x,y))是无法被拆分剩下来的余项),如此便可通过这些(log_2^{num})件的物品凑成所有可能的取值状态。
#include <cstdio>
#define MAXN 100001*20
#define MAX(A,B) ((A)>(B)?(A):(B))
using namespace std;
int n,w,cnt;
int val[MAXN],cost[MAXN];
int dp[MAXN];
int main(){
scanf("%d %d", &n, &w);
for(int i=1;i<=n;++i){
int tval,tcost,tnum;
scanf("%d %d %d", &tval, &tcost, &tnum);
for(int j=1;j<=tnum;j*=2){
val[++cnt]=tval*j;
cost[cnt]=tcost*j;
tnum-=j;
}
if(tnum!=0) val[++cnt]=tnum*tval,cost[cnt]=tnum*tcost;
}
for(int i=1;i<=cnt;++i)
for(int j=w;j>=cost[i];j--)
dp[j]=MAX(dp[j],dp[j-cost[i]]+val[i]);
printf("%d", dp[w]);
return 0;
}