網線主管(二分答案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。

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章