BUPT 2021 Winter Training #11
作者:互联网
链接:https://vjudge.net/contest/481321#overview
A - Toda 2
题意
一群玩dota的人想组个战队,然而他们的段位良莠不齐,于是决定组队掉分掉到所有人段位一样为止。由于某种原因,他们不能单人掉分,只能选择从双排到五排的多人掉分。每打一局所有人段位-1.请问他们能达到相同段位的最大值是多少,并输出整个掉分方案。
人话:n个数,每次可以从中任选2到5个同时-1.经过一些步骤后n个数全部相等,问这个相等的数最大是多少,并输出每个步骤。
思路
首先,可以简化为删除个数只有2和3,因为4和5可以由2和3组成。
显然若最大值出现了不止一次,那么从最大值开始一层一层删,因为2和3可以组成大于等于2的任意整数。
如果最大值只出现了一次,那么首先一定会把最大值删到和次大值相等。且这个过程不能动次大值,不动次大值一定必动次大值更优。那么一定先进行最大值-次大值次删2操作,其中一个删最大值,另外一个在最大值和次大值之外的值尽量平均地删。
删到最大值和次大值相等后就变成上一种情况了,继续操作即可。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
struct st1{
int x;
int num;
}lis[110];
int totans[10010][110],cnt=0;
int minimum;
bool cmp(st1 a,st1 b)
{
return a.x>b.x;
}
void oper_last1()//can
{
int k,i,j;
int a,b,c;
/*printf("******\n");
for(k=1;k<=n;k++)printf("%d ",lis[k].x);
printf("\n");*/
c=lis[1].x-lis[n].x;
for(k=0;k<c;k++)
{
for(i=1;i<=n;i++)if(lis[i].x!=lis[1].x)break;
a=i-1; b=1;
if(a&1)
{
cnt++;
for(i=1;i<=n;i++)
{
if(i==lis[1].num || i==lis[2].num || i==lis[3].num)totans[cnt][i]=1;
else totans[cnt][i]=0;
}
b=4;
}
while(b<a)
{
cnt++;
for(i=1;i<=n;i++)
{
if(i==lis[b].num || i==lis[b+1].num)totans[cnt][i]=1;
else totans[cnt][i]=0;
}
b+=2;
}
for(i=1;i<=a;i++)lis[i].x--;
/*printf("******\n");
for(i=1;i<=n;i++)printf("%d ",lis[i].x);
printf("\n");*/
}
minimum=lis[n].x;
return;
}
void oper_last2()//can't
{
int k,i,j;
for(k=0;k<lis[1].x;k++)
{
cnt++;
for(i=1;i<=n;i++)
{
if(i==lis[1].num || i==lis[2].num)totans[cnt][i]=1;
else totans[cnt][i]=0;
}
}
minimum=0;
return;
}
int find_pos()
{
int k,i,j;
for(k=n-1;k>2;k--)if(lis[k].x>lis[k+1].x)return k;
return n;
}
int main()
{
int k,i,j;
int a,b,c;
scanf("%d",&n);
for(k=1;k<=n;k++)
{
scanf("%d",&lis[k].x);
lis[k].num=k;
}
sort(lis+1,lis+n+1,cmp);
if(n==2)
{
if(lis[1].x==lis[2].x)oper_last1();
else oper_last2();
printf("%d\n%d\n",minimum,cnt);
for(k=1;k<=cnt;k++)
{
for(i=1;i<=n;i++)printf("%d",totans[k][i]);
printf("\n");
}
return 0;
}
c=lis[1].x-lis[2].x;
//printf("# %d\n",c);
for(k=0;k<c;k++)
{
a=find_pos();
if(lis[a].x==0)
{
oper_last2();
break;
}
cnt++;
for(i=1;i<=n;i++)
{
if(i==lis[1].num || i==lis[a].num)totans[cnt][i]=1;
else totans[cnt][i]=0;
}
lis[1].x--; lis[a].x--;
}
if(k==c)oper_last1();
printf("%d\n%d\n",minimum,cnt);
for(k=1;k<=cnt;k++)
{
for(i=1;i<=n;i++)printf("%d",totans[k][i]);
printf("\n");
}
return 0;
}
标签:11,Training,大值,return,int,最大值,BUPT,段位,st1 来源: https://www.cnblogs.com/teralem/p/15913674.html