POJ1064 Cable master 二分
阿新 • • 發佈:2019-01-02
題目大意:有n條繩子,長度分別為L[i]。如果從他們中切割出k條長度相同的繩子的話,這k條繩子每條最長能有多長?(答案保留小數點後兩位,規定1單位長度的繩子最多可以切割成100份)。
分析:二分搜尋最大長度x。我們令C(x)為可以得到K條長度為x的繩子,那麼問題就變為了求滿足條件C(x)的最大的x。在區間初始化時,只需使用充分大的數inf(大於繩子的最大長度的二倍)作為上界即可:left=0,right=inf。那麼現在的問題就變為了如何高效的判斷C(x)是否滿足。由於長度為L的繩子最多可以切割出floor(L/x)段長度為x的繩子,因子C(x)=floor(Li/x)的總和是否不小於k,他可以在O(n)的時間內判斷出來。
實現程式碼如下:
#include <cstdio> #include <cmath> using namespace std; const int M=10005; const double inf=200005.0; double L[M]; int n,k; bool judge(double x) { int num=0; for(int i=0;i<n;i++) num+=(int)(L[i]/x); return num>=k; } void solve() { double left=0,right=inf; for(int i=0;i<100;i++) //代替while(r>l) 避免了精度問題 { //1次迴圈可以把區間縮小一半,100次可以達到10^(-30)的精度 double mid=(left+right)/2; if(judge(mid)) left=mid; else right=mid; } printf("%.2f\n",floor(right*100)/100); } int main() { while(scanf("%d%d",&n,&k)!=-1) { for(int i=0;i<n;i++) scanf("%lf",&L[i]); solve(); } return 0; }