令 n = 1 + 2 + 4 ···,1,2,4···可以组合成 1 ~ n 的任一个数,这样转换成 01 背包的问题
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define mem(x,y) memset(x,y,sizeof x)
#define inf ~0U>>2
using namespace std;
const int maxn=20;
const int maxm=1e5+10;
int N,V,c[maxn],v[maxn],n[maxn],dp[maxm];///N 种物品,背包空间为 V,每种物品花费为 c,价值为 v,有 n个
int main()
{
while(~scanf("%d%d",&N,&V))
{
for(int i=1;i<=N;i++)
scanf("%d%d%d",&c[i],&v[i],&n[i]);
if(!V||!N) {printf("0\n");continue;}
mem(dp,0);
for(int i=1;i<=N;i++)
{
for(int j=1;;j*=2)
{
if(n[i]<=j)///最后一个数不一定是 2 的 x 次幂
{
for(int k=V;k>=n[i]*c[i];k--)
dp[k]=max(dp[k],dp[k-n[i]*c[i]]+n[i]*v[i]);
break;
}
else
{
n[i]-=j;
for(int k=V;k>=j*c[i];k--)
dp[k]=max(dp[k],dp[k-j*c[i]]+j*v[i]);
}
}
}
printf("%d\n",dp[V]);
}
return 0;
}