*题解: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;
}
posted @ 2026-05-22 14:33  yutar  阅读(6)  评论(0)    收藏  举报