BZOJ 1650 [Usaco2006 Dec]River Hopscotch 跳石子:二分

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1650

题意:

  数轴上有n个石子,第i个石头的坐标为Di,现在要从0跳到L,每次条都从一个石子跳到相邻的下一个石子。

  现在FJ允许你移走M个石子,问移走这M个石子后,相邻两个石子距离的最小值的最大值是多少。

 

题解:

  二分。

  check函数:

    (1)求出每个区间的长度len[i] = dis[i+1] - dis[i]。

    (2)对于第1到n-1个区间,如果len[i] > now,则去掉右端点的石头,cnt++。

      即:len[i+1]+=len[i]; len[i]=len[i+1];

    (3)对于第n个区间,如果len[n] > now,则只能去掉左端点的石头,cnt++。

    一旦cnt > m,就return false。

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #define MAX_N 50005
 6 
 7 using namespace std;
 8 
 9 int n,m,l;
10 int ans;
11 int dis[MAX_N];
12 int len[MAX_N];
13 
14 void read()
15 {
16     cin>>l>>n>>m;
17     dis[0]=0;
18     dis[n+1]=l;
19     for(int i=1;i<=n;i++)
20     {
21         cin>>dis[i];
22     }
23 }
24 
25 bool check(int now)
26 {
27     for(int i=0;i<=n;i++)
28     {
29         len[i]=dis[i+1]-dis[i];
30     }
31     int cnt=0;
32     for(int i=0;i<n;i++)
33     {
34         if(len[i]<now)
35         {
36             len[i+1]+=len[i];
37             len[i]=len[i+1];
38             cnt++;
39             if(cnt>m) return false;
40         }
41     }
42     if(len[n]<now && cnt+1>m) return false;
43     return true;
44 }
45 
46 void solve()
47 {
48     sort(dis+1,dis+n+1);
49     int lef=1;
50     int rig=l;
51     while(rig-lef>1)
52     {
53         int mid=(lef+rig)/2;
54         if(check(mid)) lef=mid;
55         else rig=mid;
56     }
57     if(check(rig)) ans=rig;
58     else ans=lef;
59 }
60 
61 void print()
62 {
63     cout<<ans<<endl;
64 }
65 
66 int main()
67 {
68     read();
69     solve();
70     print();
71 }

 

posted @ 2017-10-02 21:06  Leohh  阅读(167)  评论(0编辑  收藏  举报