题解 CF865B Ordering Pizza
Posted win10crz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 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;
}
逃(
以上是关于题解 CF865B Ordering Pizza的主要内容,如果未能解决你的问题,请参考以下文章
C - Ordering Pizza CodeForces - 867C 贪心 经典
CodeForces 867C Ordering Pizza 贪心,思维
Codeforces Round #437 C. Ordering Pizza
Codeforces Round #437 (Div. 2, based on MemSQL Start[c]UP 3.0 - Round 2) C. Ordering Pizza