1242:網線主管
時間限制: 1000 ms 內存限制: 65536 KB
提交數: 9785 通過數: 1925
【題目描述】
仙境的居民們決定舉辦一場程序設計區域賽。裁判委員會完全由自願組成,他們承諾要組織一次史上最公正的比賽。他們決定將選手的電腦用星形拓撲結構連接在一起,即將它們全部連到一個單一的中心服務器。爲了組織這個完全公正的比賽,裁判委員會主席提出要將所有選手的電腦等距離地圍繞在服務器周圍放置。
爲購買網線,裁判委員會聯繫了當地的一個網絡解決方案提供商,要求能夠提供一定數量的等長網線。裁判委員會希望網線越長越好,這樣選手們之間的距離可以儘可能遠一些。
該公司的網線主管承接了這個任務。他知道庫存中每條網線的長度(精確到釐米),並且只要告訴他所需的網線長度(精確到釐米),他都能夠完成對網線的切割工作。但是,這次,所需的網線長度並不知道,這讓網線主管不知所措。
你需要編寫一個程序,幫助網線主管確定一個最長的網線長度,並且按此長度對庫存中的網線進行切割,能夠得到指定數量的網線。
【輸入】
第一行包含兩個整數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
思路:1. 枚舉所有網線可能的長度(0,max] ,計算出每種長度下網線的數量
2. 時間複雜度爲 O(maxn),100km的長度 * n,必然超時,所以我們在列舉網線長度時,可以選擇二分算法。
3. 假如當前在長度區間中選擇了中間一個數mid,算出的網線數量ans >= k, 那麼就說明答案在以mid爲分界的左區間,反之則在以mid爲分界的右區間。
4. 需要注意的是精度的處理,如果是小數二分的話那就比較麻煩了,所以我們在輸入數據的時候100,讓其變成整數,輸出答案時/100即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100001
using namespace std;
int n,k,a[N];
int judge(int x)
{
int i,ans = 0;
for(i = 1;i <= n;i++)
ans += a[i]/x;
return ans >= k;
}
int main()
{
double b;
int i,j;
int left = 0,right = 0,mid;
cin >> n >> k;
for(i = 1;i <= n;i++)
{
cin >> b;
a[i] = (int)(b*100 + 0.5);
if(right < a[i])
right = a[i];
}
right += 1;
while(left+1 < right)
{
mid = (left + right)/2;
if(judge(mid))
left = mid;
else
right = mid;
}
printf("%.2lf",left/100.0);
return 0;
}