题目
1242:网线主管时间限制: 1000 ms 内存限制: 65536 KB 提交数: 23180 通过数: 5566 【题目描述】仙境的居民们决定举办一场程序设计区域赛。裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛。他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器。为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离地围绕在服务器周围放置。 为购买网线,裁判委员会联系了当地的一个网络解决方案提供商,要求能够提供一定数量的等长网线。裁判委员会希望网线越长越好,这样选手们之间的距离可以尽可能远一些。 该公司的网线主管承接了这个任务。他知道库存中每条网线的长度(精确到厘米),并且只要告诉他所需的网线长度(精确到厘米),他都能够完成对网线的切割工作。但是,这次,所需的网线长度并不知道,这让网线主管不知所措。 你需要编写一个程序,帮助网线主管确定一个最长的网线长度,并且按此长度对库存中的网线进行切割,能够得到指定数量的网线。 【输入】第一行包含两个整数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 |
思路
看题目中的数据都带小数点,似乎比较复杂(需要处理浮点数)。但仔细分析,该题的输入数据精确到厘米,要求输出结果精确到厘米,实际只要在处理过程中保持为以厘米为单位,那么该问题就转换成了整数二分的问题。
用二分思想考虑该问题,题目问:要找最长的网线长度。对应的模板为:求满足某一条件的最大值。
网线长度需要满足的条件为:将库存中的网线按mid长度进行切割,判断得到的网线数量是否居民需要的网线数量。
假设要判断为网线长度为x是否满足条件,先遍历所有库存中网线长度,每条网线长度记为l,那么l/x(整除运算)即为这条库存网线可以切出的网线的条数,求出和就是求出总条数。看处理得到的网线总条数是否居民需要的网线数量k,如果是,那么满足条件,否则不满足条件。
注意单位换算,计算过程用厘米为单位,输出时转用单位米。
代码
#include<bits/stdc++.h>
using namespace std;
long long b[10001],ans,n,s;
double t;
long long ts(int x)
{
long long int num = 0;
for(int i = 1; i <= n; i++) num += b[i] / x;
return num;
}
int f(int l,int r)
{
int mid = (l + r) / 2;
if(r - l <= 1)return l;
if(ts(mid) >= s)return f(mid,r);
else return f(l,mid);
}
int main()
{
cin>>n>>s;
for(int i = 1; i <= n; i++)
{
cin>>t;
b[i] = t * 100 + 0.1;
}
if(ts(1) < s)ans = 0;
else if(ts(1e8) >= s)ans = 1e8;
else ans = f(1,1e8);
cout<<fixed<<setprecision(2)<<ans / 100.0 + 0.0001;
return 0;
}