1.题意:一条河长为L,河上有N块石头,一只青蛙可以利用这些石头从河的一端跳到对岸,可以跳不超过M次,求各种跳法中,找到最小化的最大步长。输入第一行依次给出L、N、M,第二行依次给出N块石头距离起点的距离。
2.分析:这类最小化最大值的问题用二分来求解最高效。先预先处理,连同起点,终点,共N+2个点排序,两两相减得到N+1段距离C[i],即跨一步的最小距离。二分维护mid值,上界为河长L,下界为两两距离之中的最大值maxC[i](反证易知),以mid值分割C[i]数组,分割的段数<=M则mid偏大,反之偏小。
3.代码:
1 # include <iostream> 2 # include <cstdio> 3 # include <algorithm> 4 using namespace std; 5 const int MAXN=500005; 6 int River[MAXN]; 7 int C[MAXN]; 8 int L,N,M; 9 bool judge(int mid) 10 { 11 int sum=0; 12 int cnt=1; 13 for(int i=1;i<=N+1;i++) 14 { 15 sum+=C[i]; 16 if(sum>mid) 17 { 18 cnt++; 19 sum=C[i]; 20 } 21 } 22 if(cnt<=M) return true; 23 else return false; 24 } 25 void Init() 26 { 27 for(int i=1;i<=N;i++) 28 scanf("%d",&River[i]); 29 River[N+1]=L; 30 River[0]=0; 31 sort(River,River+N+2); 32 for(int i=1;i<=N+1;i++) 33 C[i]=River[i]-River[i-1]; 34 } 35 void Solve() 36 { 37 int l=0; 38 int r=L; 39 for(int i=1;i<=N+1;i++) 40 l=max(l,C[i]); 41 while(l<=r) 42 { 43 //printf("%d %d\n",l,r); 44 int mid=l+(r-l)/2; 45 if(judge(mid)) r=mid-1; 46 else l=mid+1; 47 } 48 printf("%d\n",l); 49 } 50 int main() 51 { 52 while(scanf("%d%d%d",&L,&N,&M)!=EOF) 53 { 54 Init(); 55 Solve(); 56 } 57 return 0; 58 }
HDU 4004 The Frog's Games 二分
时间: 2024-11-01 11:23:46