题目大意:
奇幻世界的居民最近决定举行一场区域性编程大赛,评委会志愿将这次比赛举办成一次最诚实公平的比赛。评委会决定采用星型网络拓扑结构将每个选手的电脑连接至中央服务器,并且每位选手理中央处理器的距离相同。
评委会已经和当地的网络解决方案供应商取得了联系,并且要求他们提供一定数量的且长度相同的电缆作为连接线,评委会希望电缆足够长可以使得各选手之间的距离最大。该公司的电缆专家接到了这活儿,他知道公司每一根电缆的长度(精确到厘米),如果告诉他需要的长度他可以轻而易举地进行裁剪,但是这次没有告诉他指定的长度因此他困惑了,这次需要你编程告诉专家如何确定电缆的长度。
现只有一个测例,测例中给定了电缆公司所拥有的电缆的数量N(1 ≤ N ≤ 10,000),评委会需要的电缆数量K(1 ≤ K ≤ 10,000),接下来会给出每根电缆的长度(精确到厘米),每根电缆的长度都在1米和100千米之间,现求出满足评委会要求的数量的电缆的最大长度,结果截断至两位小数(不要求四舍五入,直接截断),如果结果不到1厘米则直接输出0.00。
注释代码:
/*
* Problem ID : POJ 1064 Cable master
* Author : Lirx.t.Una
* Language : C
* Run Time : 63 ms
* Run Memory : 260 KB
*/
#include <stdio.h>
//最低精度要求
//题中要求精确到2位小数
//因此精度比要求再进一位
//经测试这也是AC的最低精度
//由于精度越高二分次数越大
//因此有必要通过降低精度的方式减少二分次数
//使运行时间达到最低
#define ESP 1E-3
//maximum number of cables
//电缆的最大数量
#define MAXCABLEN 10000
//控制精度的函数
//因为在使用printt的%lf格式(包括其他浮点数格式)时会帮你自动
//进行四舍五入,而题中要求截断至该精度,因此需要先乘100用int
//将厘米后面的位数截断,然后再除以100得到题目要求的数
#define OUT(x) ( (double)(int)( x * 100.0 ) * 0.01 )
double cab[MAXCABLEN];//length of each cable,存放各电缆的长度
int
main() {
int n, k;//电缆数(库存)和评委会要求的供应量
int i;//计数变量
int cnt;//count,记录当长度为mid时可从库存电缆切得的电缆数
double max;//库存中最长电缆的长度
//[lft, rht]表示电缆长度的可能范围
//mid为中间值,也就是用mid值来逼近最后的答案
double lft, rht, mid;
scanf("%d%d", &n, &k);
for ( max = 0, i = 0; i < n; i++ ) {
scanf("%lf", cab + i);
if ( cab[i] > max )
max = cab[i];
}
if ( 1 == k ) {//如果只要求一根电缆则直接输出最长的电缆长度
printf("%.2lf\n", OUT(max));
return 0;
}
if ( 1 == n ) {//如果库存只有一根电缆,则将该电缆均分后的长度
//就是要求结果
printf("%.2lf\n", OUT( max / (double)k ));
return 0;
}
//先初始化二分搜索的范围
lft = 0.0;
rht = max;
while ( rht - lft > ESP ) {
mid = ( lft + rht ) / 2.0;
//计算每根电缆上可以切下来几根mid长度的电缆段
for ( cnt = 0, i = 0; i < n; i++ )
cnt += (int)( cab[i] / mid );
if ( cnt >= k )//如果数量够格则继续想更长的探索
lft = mid;
else//否则就代表试探的长度太大,数量不够,则需要向跟小的长度探索
rht = mid;
}
//左值一定能行,mid和右值可能会偏大
//但是这道题刚好取右值才行
//lft和mid都太小了,只有rht能AC
printf("%.2lf\n", OUT(rht));
return 0;
}
无注释代码:
#include <stdio.h>
#define ESP 1E-3
#define MAXCABLEN 10000
#define OUT(x) ( (double)(int)( x * 100.0 ) * 0.01 )
double cab[MAXCABLEN];
int
main() {
int n, k;
int i;
int cnt;
double max;
double lft, rht, mid;
scanf("%d%d", &n, &k);
for ( max = 0, i = 0; i < n; i++ ) {
scanf("%lf", cab + i);
if ( cab[i] > max )
max = cab[i];
}
if ( 1 == k ) {
printf("%.2lf\n", OUT(max));
return 0;
}
if ( 1 == n ) {
printf("%.2lf\n", OUT( max / (double)k ));
return 0;
}
lft = 0.0;
rht = max;
while ( rht - lft > ESP ) {
mid = ( lft + rht ) / 2.0;
for ( cnt = 0, i = 0; i < n; i++ )
cnt += (int)( cab[i] / mid );
if ( cnt >= k )
lft = mid;
else
rht = mid;
}
printf("%.2lf\n", OUT(rht));
return 0;
}
单词解释:
inhabitant:n, 居民
wonderland:n, 奇境,仙境
regional:adj, 区域的,局部的
contestant:n, 竞争者
topology:n, 拓扑学
hub:n, 中心,集线器
decree:n, 法令; vt, 命令,颁布
evenly:adv, 均匀的,平衡的
cable:n, 电缆,缆绳
provider:n, 供应商
sit:vt, 安排就坐
stock:n, 库存,股票
centimeter:n, 厘米,公分
precision:n, 精度
puzzled:adj, 迷茫的,困惑的
specified:adj, 规定的,指定的
kilometer:n, 公里,千里