思维难度较大 贪心优化背包 [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;
}
相关推荐
kishu_iOS&AI1 分钟前
机器学习 —— 线性回归(2)
人工智能·python·算法·机器学习·线性回归
NULL指向我4 分钟前
信号处理学习笔记6:ADC采样线性处理实测拟合
人工智能·算法·机器学习
汽车仪器仪表相关领域6 分钟前
NHXJ-02汽车悬架检验台 实操型实战手册
人工智能·功能测试·测试工具·算法·安全·单元测试·可用性测试
源码之屋8 分钟前
计算机毕业设计:Python天气数据采集与可视化分析平台 Django框架 线性回归 数据分析 大数据 机器学习 大模型 气象数据(建议收藏)✅
人工智能·python·深度学习·算法·django·线性回归·课程设计
我爱C编程8 分钟前
【3.2】FFT/IFFT变换的数学原理概述与MATLAB仿真
算法·matlab·fpga·fft·ifft
chao18984416 分钟前
基于改进二进制粒子群算法的含需求响应机组组合问题MATLAB实现
开发语言·算法·matlab
Imxyk23 分钟前
P9242 [蓝桥杯 2023 省 B] 接龙数列
c++·算法·图论
炽烈小老头27 分钟前
【每天学习一点算法 2026/04/10】Excel表列序号
学习·算法
郝学胜-神的一滴27 分钟前
二叉树后序遍历:从递归到非递归的优雅实现
数据结构·c++·程序人生·算法·
宝贝儿好30 分钟前
【LLM】第一章:分词算法BPE、WordPiece、Unigram、分词工具jieba
人工智能·python·深度学习·神经网络·算法·语言模型·自然语言处理