切繩子-洛谷-P1577
阿新 • • 發佈:2018-12-12
原題: 有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; }