🏆今日学习目标:
🍀学习了解–04:网线主管
✅创作者:贤鱼
⏰预计时间:5分钟
🎉个人主页:贤鱼的个人主页
🔥专栏系列:c++
🍁贤鱼的个人社区,欢迎你的加入 贤鱼摆烂团
题目
-
描述
仙境的居民们决定举办一场程序设计区域赛。裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛。他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器。为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离地围绕在服务器周围放置
。 -
为购买网线,裁判委员会联系了当地的一个网络解决方案提供商,要求能够提供
一定数量的等长网线
。裁判委员会希望网线越长越好
,这样选手们之间的距离可以尽可能远一些
。 -
该公司的网线主管承接了这个任务。
他知道库存中每条网线的长度(精确到厘米)
,并且只要告诉他所需的网线长度(精确到厘米),他都能够完成对网线的切割工作。但是,这次,所需的网线长度并不知道,这让网线主管不知所措。 -
你需要编写一个程序,帮助网线主管
确定一个最长的网线长度
,并且按此长度对库存中的网线进行切割,能够得到指定数量的网线。 -
输入
第一行包含两个整数N和K
,以单个空格隔开。N(1 <= N <= 10000)
是库存中的网线数,K(1 <= K <= 10000)
是需要的网线数量。 -
接下来N行,每行一个数,为库存中每条网线的长度(单位:米)。
所有网线的长度至少1m,至多100km
。输入中的所有长度都精确到厘米,即保留到小数点后两位。 -
输出
网线主管能够从库存的网线中切出指定数量的网线的最长长度
(单位:米)。必须精确到厘米,即保留到小数点后两位。
若无法得到
长度至少为1cm的指定数量的网线,则必须输出“0.00”
(不包含引号)。
样例输入
4 11
8.02
7.43
4.57
5.39
样例输出
2.00
思路
题目要求保留小数点后两位,说明啥,如果我们要循环找答案,每次只能+0.01,不然容易错过答案,看这个数据范围,一看就炸了
- 考虑到二分
怎么分?
众所周知,二分的前提条件是内容必须有一定的规律
我们先排个序问题不大吧
- 如何排序呢
我们贤看看题目,他要求截出的导线越长越好,所以我们从小到大排序(当然从大到小也可以)
如果当前导线和
除以中间长度(我们这里导线总长不变,我们二分的是截断长度=中间长度
)
中间长度mid=(l+r)/2
如果当前数量大于目标截断数量,是不是说明还能大,所以我们截去少的一部分
举个例子
1 2 3 4 5 6 7 8 9
↓
5 6 7 8 9
是不是mid就变大了
反之,如果长度小于了,截断长度就要变小(长度大截断数量小,长度小截断数量大)
这个搞明白了题目已经做完了
AC代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
double a[100001];
int s,n;
cin>>n>>s;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i;j++){
if(a[j]>a[j+1]){
swap(a[j],a[j+1]);
}
}
}
int l=1,r=1000000000,d=0;
while(1){
int mid=(l+r)/2;
d=0;
for(int i=1;i<=n;i++){
d=d+a[i]*100/mid;
}
if(d>=s){
l=mid+1;
}else{
r=mid-1;
}
if(l>r){
printf("%.2lf",r/100.0);
return 0;
}
}
}