思维难度较大 贪心优化背包 [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;
}
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
m0_547486663 天前
《数据结构教程》全套 PPT课件2026
数据结构
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法