CF865B Ordering Pizza

  • 题目翻译:这儿有两种披萨,每份披萨分为了S块.第i个人将会吃掉Si块披萨,并且获得一些幸运值,若吃第一种披萨,每吃一块将会获得ai点幸运值,若吃第二种披萨,每吃一块将会获得bi点幸运值.我们可以任意点餐,但是最好的结果是,购买最少份数的披萨使得所有人吃上他们想要的份数.根据这个要求,能获得的最大的幸运值是多少?由样例得知一个人可以同时吃a,b两种披萨。

  • 贪心: 首先求出当每个人全部吃所获幸运值大的披萨时所得的幸运值之和ans,求出使方案合法所要损失的最小幸运值,ans-最小损失就是最后的最大幸运值。记numa为余出的a披萨的块数,numb披萨为余出的b披萨的块数,numa+numb>2s时,最大幸运值为ans,numa+numb<=ans时,此时需要让部分人改吃a披萨或者b披萨,分别计算两种情况下幸运值损失的最小值,用ans减去两者的最小值即为答案。

  • ps:检查时理清每个地方处理的思路,再检查代码的实现。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
long long n,s,si,ai,bi,numa,numb,ch,cta,ctb,ans;
struct choi{
	long long cha,num,var;//var 0 a
	bool operator<(const choi & a)const{
	return cha>a.cha;}
};
int main()
{
	priority_queue<choi>q;
	cin>>n>>s;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld%lld",&si,&ai,&bi);
		ans+=(max(ai,bi)*si);
		ai>bi?numa+=si:numb+=si;
		q.push({max(ai,bi)-min(ai,bi),si,ai>bi?0:1});
	}
	numa%=s;
	numb%=s;
//	cout<<ans<<' '<<numa<<' '<<numb<<endl;
	if(numa+numb<=s)
	{
		
		while(!q.empty()&&(numa||numb))
		{
			long long tmp;
			choi x=q.top();
			q.pop();
			if(numa&&!x.var)
			{
				tmp=min(numa,x.num);
				cta+=tmp*x.cha;
				numa-=tmp;
			}
			if(numb&&x.var)
			{
				tmp=min(numb,x.num);
				ctb+=tmp*x.cha;
				numb-=tmp;
			}			
		}
		ans-=min(cta,ctb);
	}
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈希表扁豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值