思维难度较大 贪心优化背包 [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;
}
相关推荐
七颗糖很甜10 分钟前
“十五五”气象发展规划:聚焦五大核心任务
大数据·python·算法
科研前沿17 分钟前
镜像视界浙江科技有限公司的关键技术突破有哪些?
大数据·人工智能·科技·算法·音视频·空间计算
嫩萝卜头儿26 分钟前
2 - 复杂度收尾 + 链表经典OJ
数据结构·算法·链表·复杂度
星马梦缘39 分钟前
算法设计与分析 作业二 答案与解析
算法·图论·dfs·bfs·floyd-warshall·bellman_ford·多源最短路
玛丽莲茼蒿39 分钟前
Leetcode hot100 每日温度【中等】
算法·leetcode·职场和发展
cjp5601 小时前
009.UG二次开发,任务环境草图优化3(高级功能生成直线)
算法
样例过了就是过了1 小时前
LeetCode热题100 分割等和子集
数据结构·c++·算法·leetcode·动态规划
逻辑驱动的ken1 小时前
Java高频面试考点18
java·开发语言·数据库·算法·面试·职场和发展·哈希算法
木木_王1 小时前
嵌入式Linux学习 | 数据结构 (Day05) 栈与队列详解(原理 + C 语言实现 + 实战实验 + 易错点剖析)
linux·c语言·开发语言·数据结构·笔记·学习
北顾笙9802 小时前
day38-数据结构力扣
数据结构·算法·leetcode