UVALive 7147 -智商题

来源:互联网 发布:中兴网络机顶盒说明书 编辑:程序博客网 时间:2024/04/28 01:32

UVALive 7147 World Cup

https://icpcarchive.ecs.baylor.edu/index.phpoption=com_onlinejudge&Itemid=8&page=show_problem&problem=5159

题目大意:一场比赛,赢的得A分,输的得C分,平手都得B分。有n支队伍,分别比赛一次,选前m个队伍晋级(分数相同的随机排名)。问:可能的最大落榜分数,可能的最小晋级分数。

思路:首先若A<C,交换A和C。

考虑第一个问题,贪心地让分数都尽量集中到前m+1个队伍身上,那么就要后n-m-1个队伍都给m+1个队伍最多的分数,即max{A, B}。

那么前m+1个队伍的竞技中,希望分数尽量地平均,则要赢一场便输一场,或者全部平手,则有floor(m/2)场得分为max{A + C, B + B}。

若m为奇数,那么最后一场要有一半的队伍获胜,或全部平手,此时最低分数为max{B, C}。

同样,考虑第二个问题,贪心得让后n-m+1的队伍分数都尽量少,那么久要前m-1个队伍给后n-m+1个队伍最少的分数,即min{B, C}。

那么后n-m+1个队伍的竞技中,也是希望分数尽量地平均,则要赢一场便输一场,或者全部平手,则有floor((n-m)/2)场得分为min{A + C, B + B}。

若n-m为奇数,那么最后一场要有一半的队伍获胜,或全部平手,此时最高分数为min{A, B}。

分析:

1.没有晋级的队伍最高分

将队伍分为两堆,分别为m+1,n-m-1;令第m+1个队伍就是没晋级分数最高的队伍

第m+1个人与第二堆里面的队伍的n-m-1场比赛中得分要么每场都赢,要么每场都平局

即第m+1个人的得分: (n-m-1)*max(a, b);

贪心的让第一堆的分数高,要使第m+1个队伍就是没晋级分数最高的队伍,有两种可能

(1)第一堆m场比赛中所有队伍中每个队伍赢得场数和输的场数基本相同

即第m+1个人得分 : m/2*a+m/2*c,即m/2*(a+c);

(2)第一堆m场比赛中所有队伍都平局

即第m+1个人得分: m/2*b+m/2*b,即m/2*(b+b);

与第一堆的比赛得分取以上两场比赛的最大值

即:max(m/2*(a+c),m/2*(b+b));

第一堆的m场比赛有可能是奇数场也有可能是偶数场,如果是奇数场那么第m+1个人的得分还得加上最后一场的得分,第一堆的最后一场比赛有可能输也有可能平局(不能赢,如果赢了那这个队就有可能比前m-1个队伍分高,就应该晋级),所以得分为max(b, c);

最终第m+1个人的得分为:

x = (n-m-1)*max(a, b)+max(m/2*a+m/2*c,m/2*b+m/2*b)

如果m为奇数x+= max(b, c);否则为x;

2.晋级的队伍最低分

将队伍分为两堆,分别为m-1,n-m+1;令第m个队伍就是晋级分数最低的队伍

第m个人与第一堆里面的队伍的m-1场比赛中得分要么每场都输,要么每场都平局

即第m个人的得分: (m-1)*min(c, b);

贪心的让第二堆的分数低,要使第m个队伍就是晋级分数最低的队伍,有两种可能

(1)第二堆n-m场比赛中所有队伍中每个队伍赢得场数和输的场数基本相同

即第m个人得分 : (n-m)/2*a+(n-m)/2*c,即(n-m)/2*(a+c);

(2)第一堆n-m场比赛中所有队伍都平局

即第m个人得分: (n-m)/2*b+(n-m)/2*b,即(n-m)/2*(b+b);

与第一堆的比赛得分取以上两场比赛的最小值

即:min((n-m)/2*(a+c),(n-m)/2*(b+b));

第二堆的n-m场比赛有可能是奇数场也有可能是偶数场,如果是奇数场那么第m个人的得分还得加上最后一场的得分,第一堆的最后一场比赛有可能赢也有可能平局(不能输,如果输的话,那该队得的分数就比第二堆其他队的分数低就不能晋级了),所以得分为min(b, a);

最终第m个人的得分为:

x = (m-1)min(c, b)+min((n-m)/2(a+c),(n-m)/2*(b+b))

如果n-m为奇数x+= min(b, a);否则为x;

#include<bits/stdc++.h>#define UP(i,l,h) for(int i=l;i<h;i++)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define ll long longusing namespace std;int n,m;ll a,b,c;ll solve1()//最高分{    ll ans=(ll)(n-m-1)*max(a,b);    ans+=(ll)m/2*max(b*2,a+c);    if(m&1)        ans+=max(b,c);    return ans;}ll solve2()//最低分{    ll ans=(ll)(m-1)*min(c,b);    ans+=(ll)(n-m)/2*min(b*2,a+c);    if((n-m)&1)        ans+=min(b,a);    return ans;}int main(){    int t;    int ca=1;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        scanf("%lld%lld%lld",&a,&b,&c);        if(c>a)swap(c,a);        ll ans1=solve1();        ll ans2=solve2();        printf("Case #%d: %lld %lld\n",ca++,ans1,ans2);    }}
原创粉丝点击