洛谷【P1109 学生分组】 题解

 

 

题目描述

有N组学生,给出初始时每组中的学生个数,再给出每组学生人数的上界RR和下界L(L \le R)L(LR),每次你可以在某组中选出一个学生把他安排到另外一组中,问最少要多少次才可以使NN组学生的人数都在[L,R][L,R]中。

输入格式

第一行一个整数NN,表示学生组数; n \le 50n50

第二行NN个整数,表示每组的学生个数;

第三行两个整数L,RL,R,表示下界和上界。

输出格式

一个数,表示最少的交换次数,如果不能满足题目条件输出-11

 

题解:

首先考虑一下什么时候才能满足所有组的人数都在区间[L,R]

1)人数最少:当所有组的人数都为L时,总人数最少,此时总人数=L * N

2)人数最多:当所有组的人数都为R时,总人数最少,此时总人数=R * N

所以只有在 L * N <=总人数<= R * N 时,才能满足题意,否则输出-1。下面分析一下满足题意的情况:

考虑人数多于R的小组,令X=这些小组比人数上限R多的总人数,要想满足人数在区间[L,R]内,必须把这X个人都**转出**到其他小组,所以 交换次数>=X。

考虑人数小于L的小组,令Y=这些小组比人数下限L少的总人数,要想满足人数在区间[L,R]内,必须其他组的Y个人**转入**到这几个小组,所以 交换次数>=Y。

接下来考虑X、Y的大小关系对结果的影响。

1)X>Y,先把X个学生从人数多于R的小组拿出来,把其中Y个学生分配给人数小于L的小组。然后把剩下的X-Y个学生再随便分配即可让所有小组都在区间[L,R](想想为什么不会有多于R的情况)。

2)X=Y,把X个学生从人数多于R的小组拿出来全部转入人数小于L的小组即可。

3)X<Y,把X个学生从人数多于R的小组拿出来,全部转入人数小于L的小组。然后在满足人数在[L,R]的前提下从其他小组取出Y-X个学生转入小于L的小组即可。(想想为什么不会有少于L的情况)。

所以无论哪种情况,max(X,Y)就是最终的交换次数。

代码如下:
```cpp
#include<bits/stdc++.h>
using namespace std;
int n,m=0,b=0,c=0,a[51],l,r;
int main(){
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
m=m+a[i]; //m计算总人数
}
cin>>l>>r;
if(n*r<m||m<n*l)
cout<<-1; //如果n*r小于总人数或者n*l大于总人数输出-1
else{
for(int i=1;i<=n;i++){
if(a[i]<l)
b=l-a[i]+b;
if(a[i]>r)
c=a[i]-r+c;
}
cout<<max(b,c);
}
}
```

posted @ 2020-03-15 15:49  刘通1997  阅读(775)  评论(0编辑  收藏  举报