【题目描述】
仙境的居民们决定举办一场程序设计区域赛。裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛。他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器。为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离地围绕在服务器周围放置。
为购买网线,裁判委员会联系了当地的一个网络解决方案提供商,要求能够提供一定数量的等长网线。裁判委员会希望网线越长越好,这样选手们之间的距离可以尽可能远一些。
该公司的网线主管承接了这个任务。他知道库存中每条网线的长度(精确到厘米),并且只要告诉他所需的网线长度(精确到厘米),他都能够完成对网线的切割工作。但是,这次,所需的网线长度并不知道,这让网线主管不知所措。
你需要编写一个程序,帮助网线主管确定一个最长的网线长度,并且按此长度对库存中的网线进行切割,能够得到指定数量的网线。
【输入】
第一行包含两个整数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
这道题很好,要注意很多地方的细节,最重要的要意识到浮点数求二分要固定迭代次数,或者就是转化为整数再去做
//信息学奥赛一本通1242:网线主管 测试点都可以过的最终版本
#include <iostream>
#include <cmath>
using namespace std;
double a[10001];
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
double l=0,r=100000;//切除的指定长度的网线长度进行二分
for(int cnt=0;cnt<100;cnt++) {//使用固定迭代次数,避免浮点精度问题
long long sum=0;
double mid=(l+r)/2;
if(mid < 1e-9) break;//避免除0
for(int i=1;i<=n;i++)
sum+=(long long)(a[i]/mid);
if(sum<k) r=mid;
else l=mid;
}
if(l<0.01) cout<<"0.00";
else printf("%.2lf",floor(l * 100) / 100);//向下取整不然会四舍五入
return 0;
}
/*
//信息学奥赛一本通1242:网线主管 很多测试点过不了
#include <iostream>
#include <cmath>
using namespace std;
double a[10001];
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
double l=0,r=100000;//切除的指定长度的网线长度进行二分
while(l+0.001<r) {//使用固定迭代次数,避免浮点精度问题
long long sum=0;
double mid=(l+r)/2;
if(mid < 1e-9) break;//避免除0
for(int i=1;i<=n;i++)
sum+=(long long)(a[i]/mid);
if(sum<k) r=mid;
else l=mid;
}
if(l<0.01) cout<<"0.00";
else printf("%.2lf",floor(l * 100) / 100);//向下取整不然会四舍五入
return 0;
}
*/
/*
//信息学奥赛一本通1242:网线主管 有一个测试点过不了
#include <iostream>
#include <cmath>
using namespace std;
int a[10001];
int main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
double x;
cin>>x;
a[i]=x*100;
}
int l=0,r=10000000;//切除的指定长度的网线长度进行二分
while(l+1<r) {
long long sum=0;
int mid=(l+r)/2;
for(int i=1;i<=n;i++)
sum+=(a[i]/mid);
if(sum<k) r=mid;
else l=mid;
}
if(l<1) cout<<"0.00";
else printf("%.2lf",l/100.0);//这里不能直接除100,应该除以100.0
return 0;
}
*/
/*deepseek写法
//信息学奥赛一本通1242:网线主管 测试点全部都能过
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int n, k;
cin >> n >> k;
int a[10001];
for(int i = 1; i <= n; i++){
double x;
cin >> x;
a[i] = (int)(x * 100 + 0.5);
}
// 特殊情况处理
if(k == 0){
cout << "0.00";
return 0;
}
if(k == 1){
int max_len = 0;
for(int i = 1; i <= n; i++){
if(a[i] > max_len) max_len = a[i];
}
printf("%.2lf", max_len / 100.0);
return 0;
}
int l = 1, r = 10000000; // 从1开始,避免除0
int ans = 0;
while(l <= r){
int mid = l + (r - l) / 2;
long long sum = 0;
for(int i = 1; i <= n; i++){
sum += a[i] / mid;
}
if(sum >= k){
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
if(ans < 1){
cout << "0.00";
} else {
printf("%.2lf", ans / 100.0);
}
return 0;
}
*/
二分答案求最大网线长度

9966

被折叠的 条评论
为什么被折叠?



