HDU 4004 The Frog's Games [二分]

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 }

 

posted @ 2017-07-20 21:14  cn_XuYang  阅读(165)  评论(0编辑  收藏  举报