*题解:P8903 [USACO22DEC] Bribing Friends G
解析
考虑最优方案的策略,甜筒必定只消耗在 \(X\) 最小的那几个朋友身上。故将所有朋友按 \(X\) 从小到大排序,设 \(f_{i,j}\) 表示考虑了前 \(i\) 个朋友,花费 \(j\) 个甜筒的最大受欢迎度。对应地,设 \(g_{i,j}\) 表示考虑了位于 \([i,n]\) 的朋友,花费 \(j\) 哞尼的最大受欢迎度。合并时需要枚举一个混用哞尼和甜筒的位置。转移方程就是普通的背包,在这里不多赘述。
时间复杂度 \(O(N ^ 2)\)。
代码
/*
*/
#include <bits/stdc++.h>
#define mid ((1ll * l + r) >> 1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2000 + 5,M = 10 + 5,L = 19,L2 = 17,mod = 11380;
struct F{
int p,c,x;
friend bool operator < (F a,F b){
return a.x < b.x;
}
}fd[N];
int f[N][N],g[N][N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,a,b;
cin>>n>>a>>b;
for(int i=1;i<=n;i++){
cin>>fd[i].p>>fd[i].c>>fd[i].x;
}
sort(fd + 1,fd + n + 1);
for(int i=1;i<=n;i++){
for(int j=0;j<=b;j++){
f[i][j] = f[i - 1][j];
if(j >= fd[i].c * fd[i].x){
f[i][j] = max(f[i][j],f[i - 1][j - fd[i].c * fd[i].x] + fd[i].p);
}
}
}
for(int i=n;i>=1;i--){
for(int j=0;j<=a;j++){
g[i][j] = g[i + 1][j];
if(j >= fd[i].c){
g[i][j] = max(g[i][j],g[i + 1][j - fd[i].c] + fd[i].p);
}
}
}
int res = 0;
for(int i=1;i<=n;i++){
for(int j=0;j<=fd[i].c && b >= j * fd[i].x;j++){
res = max(res,f[i - 1][b - j * fd[i].x] + g[i + 1][a - (fd[i].c - j)] + fd[i].p);
}
}
cout<<res;
return 0;
}

浙公网安备 33010602011771号