P8903
[USACO22DEC] Bribing Friends G
题目描述
Bessie 想要观看纪录片:奶牛基因组学,但她不想一个人去。不幸的是,她的朋友们没有足够的热情和她一起去!于是,Bessie 需要贿赂她的朋友们陪她去电影院。她的贿赂武器库中有两种工具:哞尼和冰激凌甜筒。
Bessie 有
Bessie 有
做法
既然每个朋友每次都只给
很可惜,并不行。就像捆绑销售,朋友只是给 Bessie 折扣,而不是直接给她钱,所以给要冰激凌最少的那个不一定是最优的。
但这为我们打开了一个思路:假设我们已经确定了最后要选哪几位朋友,那么优先给需要冰激凌最少的那位是最划算的。
所以我们先将朋友按
然后再从后往前进行一次dp,枚举有
假设
代码
不太理解的部分可以看代码。
const ll N=205;
const ll M=2005;
const ll inf=0x3f3f3f3f;
ll n,m,k,ans;
struct node{
ll a,c,x;
}a[M];
ll dp[M][M],f[M][M];
inline bool cmp(node a,node b){
return a.x<b.x;
}
inline void pre_solve(){
UF(i,n,1){
F(j,0,m) dp[i][j]=dp[i+1][j];
F(j,a[i].c,m) dp[i][j]=max(dp[i][j],dp[i+1][j-a[i].c]+a[i].a);
}
}
int main(){
n=read();m=read();k=read();
F(i,1,n) a[i].a=read(),a[i].c=read(),a[i].x=read();
sort(a+1,a+n+1,cmp);
pre_solve();
UF(i,n,1){
F(j,0,k){
f[i][j]=f[i+1][j];
ll num=min(a[i].c,j/a[i].x);
ll lst=j-num*a[i].x;
if(num==a[i].c) f[i][j]=max(f[i][j],f[i+1][lst]+a[i].a);
else f[i][j]=max(f[i][j],dp[i+1][m-(a[i].c-num)]+a[i].a);
ans=max(ans,f[i][j]);
}
}
printf("%lld\n",ans);
return 0;
}