庆功会
Description
为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。
Analysis
这题是多重背包模板题,但我也只能找到这个难度的了..
值得一提的是多重背包的拆分过程中不能用log2直接算...误差有点大,会RE70。
Code 01背包
#include <bits/stdc++.h>
const int N=6010;
int n,m,c[N],v[N],s[N],dp[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&c[i],&v[i],&s[i]);
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
for(int k=1;k<=std::min(j/c[i],s[i]);k++)
dp[j]=std::max(dp[j],dp[j-k*c[i]]+k*v[i]);
printf("%d\n",dp[m]);
return 0;
}
Code 多重背包
#include <bits/stdc++.h>
const int N=6010;
int n,m,dp[N];
struct award{
int c,v;
};
std::vector <award> a;
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int c,v,s,k;
scanf("%d%d%d",&c,&v,&s);
award temp;
for(k=0;;k++,a.push_back(temp)){
if(s<(1<<k+1)-1)break;
temp.c=(1<<k)*c;
temp.v=(1<<k)*v;
}
temp.c=(s-(1<<k)+1)*c;
temp.v=(s-(1<<k)+1)*v;
a.push_back(temp);
}
for(int i=0;i<a.size();i++)
for(int j=m;j>=a[i].c;j--)
dp[j]=std::max(dp[j],dp[j-a[i].c]+a[i].v);
printf("%d\n",dp[m]);
return 0;
}