题目来源:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=158945;
仍旧贪心.题目意思是有N个人,按比赛分数高低选取M个.选不上的最大分数和选上的最小分数.
if( A < C) swap(A,C);选不上,此时将人分为两堆.M+1,N-M-1, 要让M+1分数尽量多
则 ans1 += (M+1)*max(A,B);
接下来对于M+1内部来说,要尽量平均,两种情况都是平局,或一胜一负对半. ans1 += M/2 *max(A+C,B+B);
如果M是奇数,那么不会对半,定有一个为多输一局或仍是平局
if(M&1) ans1 += max(C,B);
同理可知选上的最小分数就是分为M-1,N-M+1 两堆,
ans2 += min(C,B)*(M-1)
接下来对于N-M+1内部来说,尽量平均,则
ans2 += (N-M)/2 *min(A+C,B+B);
如果N-M是奇数,那么不会对半,定有一个为多输一局或仍是平局
if( N-M &1) ans2 += min(A,B);
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 1100000
using namespace std;
int main(){
int T,N,M,A,B,C;
int cas = 1;
for(scanf("%d",&T);T;T--) {
scanf("%d%d",&N,&M);
scanf("%d%d%d",&A,&B,&C);
if(A<C) swap(A,C);
long long ans1=0,ans2=0;
ans1 += (N-M-1) * max(A,B);
ans1 += M/2 * max(A+C,B+B);
if(M & 1)
ans1 += max(C,B);
ans2 += (long long)(M-1) * min(B,C);
ans2 += (long long)(N-M)/2 * min(A+C,B+B);
if(N - M & 1)
ans2 += min(A,B);
printf("Case #%d: %lld %lld\n",cas++,ans1,ans2);
}
return 0;
}
这纯粹是转载大神的代码.之所以还写;
就是因为有一个坑于我而言太深。
就是
如果M是奇数,那么不会对半,定有一个为多输一局或仍是平局
if(M&1) ans1 += max(C,B);
如果N-M是奇数,那么不会对半,定有一个为多输一局或仍是平局
if( N-M &1) ans2 += min(A,B);
奇数并没有拿出来特殊考虑,结果卡好久。。。
当初觉得奇数的时候可能有点不一样,却没有在多加考虑,好吧我得承认最近越来越二了。