分数规划模板(洛谷P4377 [USACO18OPEN]Talent Show)(分数规划,二分答案,背包)

分数规划是这样一个东西:

给定若干元素,每个元素有两个属性值ai,bi,在满足题目要求的某些限制下选择若干元素并求出ab的最大值。

如果没有限制的话,肯定是贪心的选。

假设当前选择了一个解x0,却并不是ab的最大值,我们有

ab>x0

进而

abx0>0

这时候我们要求的东西变成了abx0,每个元素的贡献就独立了。最大化它的和,如果大于0,就说明ab的最大值比x0还要大,反之亦然。

于是我们就不难想到二分了。控制x0的上下界,每次取mid进行求值并判断。

例题:洛谷P4377 [USACO18OPEN]Talent Show

此题的限制是b不小于于给定值,以b的和为下标,每选一个物品后用背包转移即可。复杂度O(nWlogna)

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
#define G if(++ip==ie)fread(ip=buf,1,SZ,stdin)
using namespace std;
const LL SZ=1<<19,N=1009,INF=0xc0c0c0c0c0c0c0c0;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
int t[N],w[N];
LL f[N];
inline int in(){
	G;while(*ip<'-')G;
	R x=*ip&15;G;
	while(*ip>'-'){x*=10;x+=*ip&15;G;}
	return x;
}
inline void chkmx(RG LL&x,RG LL y){
	if(x<y)x=y;
}
int main(){
	R n=in(),W=in(),i,j,l=0,r=2500000,m;
	RG LL del;
	for(i=1;i<=n;++i)
		w[i]=in(),t[i]=in()*1000;
	while(l<r){
		m=(l+r+1)>>1;
		memset(f+1,128,W<<3);
		for(i=1;i<=n;++i){
			del=t[i]-(LL)w[i]*m;
			for(j=W;~j;--j)
				if(f[j]!=INF)chkmx(f[min(j+w[i],W)],f[j]+del);
		}
		f[W]>=0?l=m:r=m-1;
	}
	printf("%d\n",l);
	return 0;
}
posted @   Flash_Hu  阅读(370)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
剑桥
17:14发布
剑桥
17:14发布
5°
西风
7级
空气质量
相对湿度
34%
今天
多云
-3°/5°
周六
-1°/3°
周日
-2°/7°