C-签到题
一、题目描述
SDUQD 旁边的滨海公园有 x 条长凳。第 i 个长凳上坐着 a_i 个人。
这时候又有 y 个人将来到公园,他们将选择坐在某些公园中的长凳上,
那么当这 y 个人坐下后,记k = 所有椅子上的人数的最大值,那么k可能的最大值mx和最小值mn分别是多少。
Input
第一行包含一个整数 x (1 <= x <= 100) 表示公园中长椅的数目
第二行包含一个整数 y (1 <= y <= 1000) 表示有 y 个人来到公园
接下来 x 个整数 a_i (1<=a_i<=100),表示初始时公园长椅上坐着的人数
Output
输出 mn 和 mx
Input Example
3
7
1
6
1
Output Example
6 13
样例解释
最初三张椅子的人数分别为 1 6 1
接下来来了7个人。
可能出现的情况为{1 6 8},{1,7,7},…,{8,6,1}
相对应的k分别为8,7,…,8
其中,状态{1,13,1}的k = 13,为mx
状态{4,6,5}和状态{5,6,4}的k = 6,为mn
二、思路与算法
本题主要考察思维,代码没有很大难度。
主要思想为,首先,求mx非常简单,找到目前人数最多的椅子,让新来的y个人都坐在这个椅子上,mx=目前人数最多椅子的人数+y,输出即可。
而计算mn时,需要几个阶段。第一个阶段,补除了目前人数最多的椅子的椅子,把它们都补到目前最大人数,在这个期间,椅子上的最大人数不会改变。若y在这个阶段内用完了,那么mn就是目前椅子上的最大人数。如果y补完之后还有剩余,那么进入第二阶段。
第二阶段中,给每个椅子分剩下的人,一个椅子一个,循环分配直到分配完。
这样最后得到的人数最多的椅子的人数就是mn,可以直接输出。
在写代码时,可以按照这样阶段的写,但是会比较麻烦,可以采用下面提供的代码这样,先计算每个椅子达到目前最大人数所缺的总人数,如果这个数小于y,就是第一阶段就完成了,如果大于y,那么再计算剩余人数除以椅子数的余数。
如果余数为0,mn=目前最大人数+剩余人数除以椅子数。
如果余数不为0,mn=目前最大人数+剩余人数除以椅子数+1。
(因为求的是最小的最大值,所以要加一)
三、代码实现
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int x=0;
int y=0;
vector<int> people(0);
int main(){
scanf("%d",&x);
scanf("%d",&y);
for(int i=0;i<x;i++){
int tmp=0;
scanf("%d",&tmp);
people.push_back(tmp);
}
sort(people.begin(),people.end());
int mx=0;
mx=people[people.size()-1]+y;
int mn=0;
int remain=y;
int the_max=people[people.size()-1];
int sum=0;
for(int i=0;i<people.size();i++){
sum=sum+(the_max-people[i]);
}
if(sum<=y){
int yushu=(y-sum)%people.size();
if(yushu==0){mn=the_max+(y-sum)/people.size();}
else{mn=the_max+(y-sum)/people.size()+1;}
}
else{
mn=the_max;
}
printf("%d %d",mn,mx);
return 0;
}
四、经验与总结
- 在思考好整个求解流程之后,不要激动,应该再想一想,怎么归纳一下,让程序更简洁,不是每一步好几个判断,很繁琐的那种,要思考怎么去归纳在一起,多个情况合并,多个步骤合并,代码简洁干净也更不容易出错。