欲望以提升热忱,毅力以磨平高山!|

XichenOC

园龄:1个月粉丝:4关注:0

2025-01-20 19:33阅读: 5评论: 0推荐: 0

P4653 [CEOI2017] Sure Bet

P4653 [CEOI2017] Sure Bet

题目翻译:

我们可以选取任意数量的灯泡,其中灯泡有两种,每一个灯泡都有一个价值,而每取一个灯泡都会消耗一个价值,而我们要求的是,最后若只计算一种种类的灯泡的话,那获得价值较小的最大值。

思路分析:

我们根据题意可已发现我们的目标:若所选第一种的灯泡的总价值为\(a\),第二种为 \(b\)。总共取了 \(k\) 个灯泡,那最终答案就是 \(min(a-k,b-k)\) 我们就是要找一个方案使这一个的值最大。可以很明显发现以下性质:

  • 最后求得的 \(a\)\(b\) 差要尽可能少,因为反正都是找最小值,那大的就没必要再花费价值去选了。
  • 如果一个灯泡的价值越大,就越有必要选,因为最后获得价值是更高的。所以一定是从大往小选。

因此我们只需要贪心一下,从大往小选,其中还要尽量满足两种类的价值不相差太大即可

实现:

1.先将价值从大到小排序
2.在维护一个 \(suma\) \(sumb\),来储存当前选到价值
3.若 \(suma>sumb\) 那就选第二类的
4.反之就选第一类的
5.每次选择都维护最大值 \(ans\) 即可

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
double a[N],b[N];
int visa[N],visb[N];
bool cmp(double x,double y){
	return x>y;
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&a[i],&b[i]);
	}
	sort(a+1,a+n+1,cmp);
	sort(b+1,b+n+1,cmp);
	double suma=0,sumb=0,ans=0;
	for(int i=1,j=1;i<=n && j<=n;){
		suma+=visa[i]?0:a[i];
		sumb+=visb[j]?0:b[j];
		visa[i]=1;
		visb[j]=1; 
		ans=max(min(suma-i-j,sumb-i-j),ans);
		if(suma<=sumb)i++;
		if(sumb<=suma)j++;
	}
	printf("%.4lf",ans);
} 

本文作者:XichenOC

本文链接:https://www.cnblogs.com/XichenOC/p/18682402

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   XichenOC  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起