Live2D

[20191004机房测试] C++锦标赛

有一个比赛已经有 n 个人参加,并且互相之间已经进行了比赛
每一个人都有一个得分用于最后排名
你作为第 n + 1 个参赛者,需要与之前的每一个人打一场比赛,初始得分为 0
对于每场比赛,有两个人参加,不会存在平局,胜者得分增加 1,败者得分不变
最后按照得分从高到低来排名,假设有人与你最终得分相同
那么如果那个人曾经输给了你就会排在你后面,否则会排在你的前面
如果你赢了某个人,就需要消耗相应的 RP 值
现在你可以决定赢那些人,求最少需要消耗多少 RP 值才能到前k名

50分做法:还是枚举二进制串……居然有50分

100分做法:
这个满分做法是真的玄学,我们需要分三种情况讨论来贪心求解:

  1. 如果一个人的胜场和自己相同或者刚好少1,不打就会被挤下去,打了就可以升一位
  2. 如果一个人的胜场比自己多,打不打都没什么差异……
  3. 如果一个人的胜场比自己少2或者更多,那就可以不用打了
    然后贪心就好

代码:

#include<bits/stdc++.h>
#define ll long long
#define maxn 2505
using namespace std;

int T,n,k,gol,num;
ll ans;
bool used[maxn];

struct People
{
	int p, e;
}p[maxn];

bool cmp1(People x, People y) {return x.p > y.p;}
bool cmp2(People x, People y) {return x.e < y.e;}

bool check()
{
	int res=0;
	for(register int i=1;i<=n;++i)
		if(p[i].p>n) res++;
	return res>=k;
}

ll work1()
{
	ll ret=0;	
	int cnt=gol,num1=0,num2=num;
	for(register int i=1;i<=n;++i)
	{
		used[i]=0;
		if(p[i].p==gol-1) ++num1; 
	}
	for(register int i=1;i<=n&&num2;++i)
	{
		if(p[i].p==gol)
		{
			ret=ret+p[i].e;	
			used[i]=1;
			--cnt;
			--num2;
		}
	}
	for(register int i=1;i<=n&&num1;++i)
	{
		if(!used[i]&&(p[i].p==gol||p[i].p==gol-1))
		{
			ret=ret+p[i].e;	
			used[i]=1;
			--cnt;
			--num1;
		}
	}
	for(register int i=1;i<=n&&cnt;++i)
	{
		if(!used[i])
		{
			ret=ret+p[i].e;
			--cnt;
		}
	}
	return ret;
}

ll work2()
{
	ll ret=0;
	int num2=num,cnt=gol+1;
	for(register int i=1;i<=n;++i) used[i]=0;
	for(register int i=1;i<=n&&num2;++i)
	{
		if(p[i].p==gol||p[i].p==gol+1)
		{
			used[i]=1;
			ret=ret+p[i].e;
			--cnt;
			--num2;
		}
	}
	for(register int i=1;i<=n&&cnt;++i)
	{
		if(!used[i])
		{
			ret=ret+p[i].e;
			--cnt;
		}
	}
	return ret;
}

ll work3()
{
	ll ret=0;
	for(register int i=1;i<=gol+2;++i)
		ret=ret+p[i].e;
	return ret;
}

template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

int main()
{
	freopen("tournament.in","r",stdin);
	freopen("tournament.out","w",stdout);
	read(T);
	while(T--)
	{
		read(n);read(k);
		for(register int i=1;i<=n;++i) scanf("%d%d",&p[i].p,&p[i].e);
		if(k==n+1)
		{
			printf("0\n");
			continue;
		}
		if(check())
		{
			printf("-1\n");
			continue;
		}
		sort(p+1,p+n+1,cmp1);
		gol=p[k].p;
		num=1;
		while(p[k+num].p==p[k].p&&k+num<=n)	++num;
		sort(p+1,p+n+1,cmp2);
		ans=min(work1(),min(work2(),work3()));
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2019-10-04 19:11  tqr06  阅读(166)  评论(0编辑  收藏  举报