思维难度较大 贪心优化背包 [USACO22DEC] Bribing Friends G

[USACO22DEC] Bribing Friends G

显然背包可做, 只不过时间复杂度预计 O ( n 4 ) O(n^4) O(n4), 严重超时. 但是考场上写出暴力背包已经可以拿 75 分了, Oier 狂喜. 但可惜, 我打 Acm .

于是我们不妨想想怎么优化.

如果我们已经确定了选哪几位朋友, 那么把冰淇凌给需求冰淇凌最少的那头牛就行. 于是我们不妨按照 x x x 从大到小排序. 首先设 f ( i , j ) f(i,j) f(i,j) 表示前 i i i 项当我们用了 j j j 元后的好感度总和, 显然有

f ( i , j ) = { f ( i − 1 , j ) j < c min ⁡ { f ( i − 1 , j ) , f ( i − 1 , j − c ) + p } c ≤ j ≤ B f(i,j)=\begin{cases}f(i-1,j)\ \ \ \ \ j<c\\ \min\left\{f(i-1,j),f(i-1,j-c)+p\right\}\ \ \ \ c\le j\le B\end{cases} f(i,j)={f(i−1,j) j<cmin{f(i−1,j),f(i−1,j−c)+p} c≤j≤B

cpp 复制代码
for(int i=1;i<=n;P(i)){
	for(int j=0;j<cow[i].c;P(j))f[i][j]=f[i-1][j];
	for(int j=cow[i].c;j<=A;P(j))f[i][j]=std::max(f[i-1][j],f[i-1][j-cow[i].c]+cow[i].p);
}

我们不妨再设 f 1 ( i , j ) f_1(i,j) f1(i,j) 为前 i i i 项我们用 j j j 个甜筒后可获取的最大受欢迎度. 显然我们最多可以减少 r e d u c e = min ⁡ { c , j / x } reduce=\min\{c,j/x\} reduce=min{c,j/x} 元, 同样我们剩下 r e s t = j − r e d u c e ∗ x rest=j-reduce*x rest=j−reduce∗x 个冰淇淋. 显然当我们减少的钱够贿赂一头牛的钱后显然我们不需要给这头牛任何钱了, 我们可以拿剩余的冰淇淋去给其它奶牛:

f 1 ( i , j ) = max ⁡ { f 1 ( i − 1 , j ) , f 1 ( i − 1 , r e s t ) + p } f_1(i,j)=\max\left\{f_1(i-1,j),f_1(i-1,rest)+p\right\} f1(i,j)=max{f1(i−1,j),f1(i−1,rest)+p}

否则说明我们不能完全通过冰淇淋收买这头奶牛, 还是要给钱, 并且由于我们的奶牛 x x x 是降序, 这也说明之前的牛并不能被收买, 我们预处理的 f f f 就在这里派上用场了:

f 1 ( i , j ) = max ⁡ { f 1 ( i − 1 , j ) , f ( i − 1 , A − ( c − r e d u c e ) ) + p } f_1(i,j)=\max\left\{f_1(i-1,j),f\left(i-1,A-(c-reduce)\right)+p\right\} f1(i,j)=max{f1(i−1,j),f(i−1,A−(c−reduce))+p}

cpp 复制代码
for(int i=1,reduce,rest;i<=n;P(i)){
	for(int j=0;j<=B;P(j)){
		reduce=std::min(cow[i].c,j/cow[i].x);
		rest=j-reduce*cow[i].x;
		if(reduce^cow[i].c)f1[i][j]=std::max(f1[i-1][j],f[i-1][A-(cow[i].c-reduce)]+cow[i].p);
		else f1[i][j]=std::max(f1[i-1][j],f1[i-1][rest]+cow[i].p);
		ans=std::max(ans,f1[i][j]);
	}
}

总代码:

cpp 复制代码
#include<algorithm>
#include<iostream>
#define P(A) A=-~A
typedef long long LL;
#define NUMBER1 2000
int n,A,B,f[NUMBER1+5][NUMBER1+5],f1[NUMBER1+5][NUMBER1+5],ans(0);
struct COW{
	int p,c,x;
	bool operator<(const COW &A)const{return x>A.x;}
}cow[NUMBER1+5];
signed main(){
	std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
	std::cout.tie(nullptr);
	std::cin>>n>>A>>B;
	for(int i=1;i<=n;P(i))std::cin>>cow[i].p>>cow[i].c>>cow[i].x;
	std::sort(cow+1,cow+1+n);
	for(int i=1,reduce,rest;i<=n;P(i)){
		for(int j=0;j<cow[i].c;P(j))f[i][j]=f[i-1][j];
		for(int j=cow[i].c;j<=A;P(j))f[i][j]=std::max(f[i-1][j],f[i-1][j-cow[i].c]+cow[i].p);
		for(int j=0;j<=B;P(j)){
			reduce=std::min(cow[i].c,j/cow[i].x);
			rest=j-reduce*cow[i].x;
			if(reduce^cow[i].c)f1[i][j]=std::max(f1[i-1][j],f[i-1][A-(cow[i].c-reduce)]+cow[i].p);
			else f1[i][j]=std::max(f1[i-1][j],f1[i-1][rest]+cow[i].p);
			ans=std::max(ans,f1[i][j]);
		}
	}
	std::cout<<ans;
	return 0;
}
相关推荐
tankeven5 分钟前
HJ138 在树上游玩
c++·算法
北顾笙9806 分钟前
测开准备-day01数据结构力扣
数据结构
lihihi38 分钟前
P1209 [USACO1.3] 修理牛棚 Barn Repair
算法
博界IT精灵1 小时前
栈在表达式求值中的应用(暂时看到视频3.3.2_1的25min19秒)
数据结构
weixin_387534221 小时前
Ownership - Rust Hardcore Head to Toe
开发语言·后端·算法·rust
庞轩px1 小时前
MinorGC的完整流程与复制算法深度解析
java·jvm·算法·性能优化
Queenie_Charlie1 小时前
Manacher算法
c++·算法·manacher
闻缺陷则喜何志丹1 小时前
【树的直径 离散化】 P7807 魔力滋生|普及+
c++·算法·洛谷·离散化·树的直径
AI_Ming1 小时前
Seq2Seq-大模型知识点(程序员转行AI大模型学习)
算法·ai编程
若水不如远方1 小时前
分布式一致性(六):拥抱可用性 —— 最终一致性与 Gossip 协议
分布式·后端·算法