ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 CF865B 【Ordering Pizza】

2020-05-09 19:51:44  阅读:297  来源: 互联网

标签:val Ordering 题解 披萨 sum2 CF865B num long sum1


可能大家都没理解这题的意思,翻译和原文都比较含糊,我来用人话说一遍:

有 \(n\) 个人一起去买披萨。披萨店有两种披萨,每种的每个披萨都可以分成 \(s\) 片。每个人买不同数量的披萨(以片为单位),不同的人买不同种类的披萨所获得的快乐值不同。问在买披萨数量最小的情况下,如何分配买 1 号披萨和 2 号披萨的数量,使获得的快乐值总和最大。


单纯不懂题意的 dalao 到这里就可以结束了,接下来就是分析了

这题我们可以用贪心的思路来做,把买披萨的人分为两类:买 1 号披萨快乐值多的,和买 2 号披萨快乐值多的。然后分别解决两边的情况。当每片披萨的块数不能被这两类的数量分别整除时,就要确定剩下的人买 1 号披萨还是买 2 号披萨。

这里就是最麻烦的地方,我们将两类人按照两种披萨的差价排序,从小到大将剩下的块数补上,分别计算两种方法的损失,然后就按照损失小的方案输出。

高高兴兴的打出了代码:

#include<bits/stdc++.h>
using namespace std;
#define rg register
struct node
{
	long long num,val;    //num 为这个人需要的块数,val 为差价。 
}x[100005],y[100005];     //两类人。 
long long n,s,ans,m,a,b,cnt1,cnt2,sum1,sum2;
long long loss1,loss2;   //不同方案的损失。 
inline bool cmp(node x,node y)
{
	return x.val<y.val;   //按差价从小到大排序。 
}
int main()
{
	cin>>n>>s;
	for(rg int i=1;i<=n;++i)
	{
		cin>>m>>a>>b;
		if(a>b)         //买第一种更开心。 
		{
			x[cnt1].num=m;
			x[cnt1].val=a-b;
			++cnt1;
			sum1+=m;    //计算买第一种的人的总块数。 
			ans+=a*m;   //计算理想值。 
		}
		else            //同上。 
		{
			y[cnt2].num=m;
			y[cnt2].val=b-a;
			++cnt2;
			sum2+=m;
			ans+=b*m;
		}
	}
	sum1%=s;     
	sum2%=s;          //求剩下的孤零零的披萨。 
	sort(&x[0],&x[cnt1],cmp);
	sort(&y[0],&y[cnt2],cmp);
	for(rg int i=0;i<cnt1;++i)   //分别计算损失。 
	{
		if(sum1>=x[i].num)     //孤零零的披萨还有: 
		{
			sum1-=x[i].num;     //抱团。 
			loss1+=x[i].val*x[i].num;    //减去损失。 
		}
		else     //没有了! 
		{
			loss1+=sum1*x[i].val;
			break;      //计算,然后跳出。 
		}
	}
	for(rg int i=0;i<cnt2;++i)   //同上。 
	{
		if(sum2>=y[i].num)
		{
			sum2-=y[i].num;
			loss2+=y[i].val*y[i].num;
		}
		else
		{
			loss2+=sum2*y[i].val;
			break;
		}
	}
	cout<<ans-min(loss1,loss2);   //挑最优的方案。 
	return 0;
} 

然后:

悲催的评测结果

第一个点就 WA 了……


为什么?其实我们忽略了一种情况,就是两种剩下的总和大于 \(s\),这时候无论怎么做都还要两块披萨,那就豪一把,直接一种一块披萨(答案就是理想值):

	if(sum1+sum2>s)
	{
	   cout<<ans;
	   return 0;
	}

绿了!


高清 AC 无注释代码:

#include<bits/stdc++.h>
using namespace std;
#define rg register
struct node
{
	long long num,val;
}x[100005],y[100005];
long long n,s,ans,m,a,b,cnt1,cnt2,sum1,sum2;
long long loss1,loss2;
inline bool cmp(node x,node y)
{
	return x.val<y.val;
}
int mian()
{
	cin>>n>>s;
	for(rg int i=1;i<=n;++i)
	{
		cin>>m>>a>>b;
		if(a>b)
		{
			x[cnt1].num=m;
			x[cnt1].val=a-b;
			++cnt1;
			sum1+=m;
			ans+=a*m;
		}
		else
		{
			y[cnt2].num=m;
			y[cnt2].val=b-a;
			++cnt2;
			sum2+=m;
			ans+=b*m;
		}
	}
	sum1%=s;
	sum2%=s;
	if(sum1+sum2>s)
	{
	   cout<<ans;
	   return 0;
	}
	sort(&x[0],&x[cnt1],cmp);
	sort(&y[0],&y[cnt2],cmp);
	for(rg int i=0;i<cnt1;++i)
	{
		if(sum1>=x[i].num)
		{
			sum1-=x[i].num;
			loss1+=x[i].val*x[i].num;
		}
		else
		{
			loss1+=sum1*x[i].val;
			break;
		}
	}
	for(rg int i=0;i<cnt2;++i)
	{
		if(sum2>=y[i].num)
		{
			sum2-=y[i].num;
			loss2+=y[i].val*y[i].num;
		}
		else
		{
			loss2+=sum2*y[i].val;
			break;
		}
	}
	cout<<ans-min(loss1,loss2);
	return 0;
} 

逃(

标签:val,Ordering,题解,披萨,sum2,CF865B,num,long,sum1
来源: https://www.cnblogs.com/win10crz/p/12859785.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有