-
题目翻译:这儿有两种披萨,每份披萨分为了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;
}