1. 程式人生 > >切繩子-洛谷-P1577

切繩子-洛谷-P1577

原題: 有N條繩子,它們的長度分別為Li。如果從它們中切割出K條長度相同的繩子,這K條繩子每條最長能有多長?答案保留到小數點後2位。 輸入輸出格式 輸入格式: 第一行兩個整數N和K,接下來N行,描述了每條繩子的長度Li。 輸出格式: 切割後每條繩子的最大長度。 輸入輸出樣例 輸入樣例#1: 複製 4 11 8.02 7.43 4.57 5.39 輸出樣例#1: 複製 2.00 說明 對於100%的資料 0<Li<=100000.00 0<n<=10000 0<k<=10000 題意: 有n條長度不一的繩子,你需要切成k個長度相同的繩子,問能切出繩子的最大長度? 題解: 對於這個問題,思想上就是一個簡單的二分問題。定義一個最優解,每一次都判斷能否在當前這個最大長度下切出k個繩子,若能則證明m最大長度取小了,反之則大了。 這道題目容易卡的就是精度,題目要求輸出小數點後兩位數字,這個問題我最先想到的直接就用double型的解決,卻總是會WA掉幾個測試點。其實可以換一個思路來想,我把先將每一個數值擴大一百倍,當作整型來處理,就不會受到精度的影響,之後再在結果上除去100即可。 附上AC程式碼:

#include <iostream>
#include <iomanip>
using namespace std;
int n;
double k,a[100005];
bool check(double m)
{
    int sum=0;//記錄能切出多少個長度為m的繩子
    for(int i=1;i<=n;i++)
    {
        sum+=(int)(a[i]/m);
    }
    if(sum>=k)
        return true;
    else return false;
}
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        a[i]*=100;//將資料先擴大100倍
    }
    int l=0,m,r=100000000;//定義上下界,r可以開大一些
    while(l<=r)
    {
        m=(l+r)/2;
        if(m==0)break;//增強健壯性
        if(check(m))
          l=m+1;
        else
            r=m-1;
    }
    cout<<fixed<<setprecision(2)<<1.0*r/100<<endl;//輸出時,先將其*1.0轉變成浮點數,後再出去開始擴大的100倍
    return 0;
}