题解:B2173 多重背包
B2173 多重背包
解析
本题为多重背包模版题。
首先可以想到用动态规划,设
注意要保证
但是本题中物品不只有一个,因此我们可以把它们拆成多个单一物品,存在数组中再进行动态规划。但这么做会超时!
这时我们可以用二进制拆分物品数量,将拆分后的物品依次组合成新的一件,随后再进行存储并进行动态规划。举个例子,设某件物品数量为
注意拆分时,剩下的部分也要存进去!
代码
#include<bits/stdc++.h>
#define f first
#define s second
using namespace std;
int t,m,dp[100005];
int n=1;
pair<int,int>a[100005];
int main(){
scanf("%d%d",&m,&t);
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&y,&z,&x);
for(int j=0;j<=40;j++){
int k=(1<<j);
if(k<=x){//可以就拆
x-=k;
a[n].f=y*k,a[n].s=z*k;//别忘记乘
++n;
}else break;
}
if(x){//注意剩余部分
a[n].f=y*x,a[n].s=z*x;
++n;
}
}
for(int i=1;i<=n;i++){//普通背包
for(int j=t;j>=a[i].f;j--){
dp[j]=max(dp[j],dp[j-a[i].f]+a[i].s);
}
}printf("%d",dp[t]);
return 0;
}