zoukankan      html  css  js  c++  java
  • 题解 CF865B 【Ordering Pizza】

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

    (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;
    } 
    

    逃(

  • 相关阅读:
    第四周JSP作业
    jsp第二次作业
    3.4软件管理与测试作业
    jsp3月3日作业
    课后listview作业
    安卓sql
    activity带数据跳转
    answers
    阿里云ESC无法使用python发送邮件的问题
    Ubuntu 更改时区
  • 原文地址:https://www.cnblogs.com/win10crz/p/12859785.html
Copyright © 2011-2022 走看看