网线主管(二分答案or二分搜索)

Description
仙境的居民们决定举办一场程序设计区域赛。裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛。他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器。为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离地围绕在服务器周围放置。

为购买网线,裁判委员会联系了当地的一个网络解决方案提供商,要求能够提供一定数量的等长网线裁判委员会希望网线越长越好,这样选手们之间的距离可以尽可能远一些。

该公司的网线主管承接了这个任务。他知道库存中每条网线的长度(精确到厘米),并且只要告诉他所需的网线长度(精确到厘米),他都能够完成对网线的切割工作。但是,这次,所需的网线长度并不知道,这让网线主管不知所措。

你需要编写一个程序,帮助网线主管确定一个最长的网线长度,并且按此长度对库存中的网线进行切割,能够得到指定数量的网线。

Input
第一行包含两个整数N和K,以单个空格隔开。N是库存中的网线数,K是需要的网线数量。

接下来N行,每行一个数,为库存中每条网线的长度(单位:米)。所有网线的长度至少1m,至多100km。输入中的所有长度都精确到厘米,即保留到小数点后两位

Output
网线主管能够从库存的网线中切出指定数量的网线的最长长度(单位:米)。必须精确到厘米,即保留到小数点后两位

若无法得到长度至少为1cm的指定数量的网线,则必须输出"0.00"(不包含引号)

Sample Input 1
4 11
8.02
7.43
4.57
5.39
Sample Output 1
2.00

Hint
1≤N≤10000,1≤K≤10000
Time Limit
1000MS
Memory Limit
256MB

分析:
题目核心意思是要在网线数量够的前提下确定网线的最大长度。当确定一个长度,分割得的网线数不小于要求数,就说明按这个长度分割是够用的,可以尝试更大的长度,如果该长度分割得的网线数比要求数少,就说明分割得太长了,得把长度减小。分析到这里,就明白这是个妥妥的二分答案题,需要把网线分割长度二分再搜索。
不过这道题目的特别之处在于网线长度数据都是浮点数,精确到小数点后两位,为了使数据处理起来方便,可以把网线长度乘以100(化为整数)再处理。
另外,题目要求当网线长度连1cm都满足不了时输出“0.00”,可以令记录答案的变量初值ans为0,这样在二分过程中,如果连1cm都满足不了,那直到退出循环ans也不会被再次赋值,仍是0。出二分循环后特判一下就好了。本人根据提交情况认为此处有坑,虽然可以不特判,printf("%.2f",ans/100.0)也可以做到输出浮点数0.00,但是题目意思应该是要输出一个字符串,所以我没加特判的时候是PA,加了以后才AC。

扫描二维码关注公众号,回复: 11653335 查看本文章
#include<stdio.h>
#include<algorithm>

int N, K;//库存网线数,需要网线数
int a[10000] = {
    
     0 };//保存库存网线数据
int ans=0,*max;//记录答案,库存网线最大长度
double temp;//接收库存网线数据的工具

int cnt(int l)//计算库存网线可以分得长度为l的网线多少根
{
    
    
	int sum = 0;
	for (int i = 0; i < N; i++)
	{
    
    
		sum += a[i] / l;
	}
	return sum;
}

int main()
{
    
    
	scanf("%d%d", &N, &K);
	for (int i = 0; i < N; i++)
	{
    
    
		scanf("%lf", &temp);
		a[i] = 100 * temp;//数据整型化处理
	}
	//找最大值,需注意,该函数返回的是一迭代器
	max = std::max_element(a, a + N);
	//左开右开写法,区间为(0,*max+1)
	int left = 0, right = *max + 1,mid,sum;
	while (left + 1 != right)
	{
    
       //本来就是要找网线可分割最大长度,不妨向上取整
		mid = left + ((right - left + 1) >> 1);
		sum = cnt(mid);
		if (sum >= K) {
    
    //满足题意
			ans = mid;//记录答案
			left = mid;//继续往右搜索
		}
		else if (sum < K) {
    
    //不满足题意,网线太长
			right = mid;//往左搜索
		}
	}
	//虽然连1cm都满足不了时ans=0,0/100.0在“%.2f”控制下可输出0.00
	if (ans < 1) {
    
    //但去掉特判就不能AC了,不知道为什么
		printf("0.00");//可能是因为题目要求输出字符串?
	}
	else printf("%.2f", ans / 100.0);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44643644/article/details/105901904
今日推荐