poj 3258 River Hopscotch

River Hopscotch
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 15663   Accepted: 6620

Description

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 ≤ MN).

FJ wants to know exactly how much he can increase the shortest distance *before* he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input

Line 1: Three space-separated integers: L, N, and M Lines 2..N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.

Output

Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks

Sample Input

25 5 2
2
14
11
21
17

Sample Output

4


二分

//解析(转)

做题思想:二分所求的最小距离的最大值mid,记录可以去掉的石头块数cnt(注意:当相邻的石头的距离小于等于mid,就可以去掉),

                  若cnt > M,h = h - 1 (这里是比较难理解的,也是我纠结挺久的地方),此时,应当回过头来看一下题目求的是什么:

                                                      寻找一个长度mid,使得可以去掉M块石头,剩下的石头中,石头间的最小距离为mid

                                                      但是cnt记录的是:相邻距离小于等于mid的块数,所以存在这样的一种情况  ---- cnt记录的所有石头中,

                                                      有很多块石头间的距离是等于mid,而距离小于mid的石头的块数是小于等于M的,此时,若将h的值减一,

                                                      那么h的值就变成一个小于题目所求的答案了。

                                                      举个例子就懂了:假设有9块石头,首尾的数都表示河岸。

                   石头的编号                      1     2     3     4     5        6         7     8      9  

                   石头到河岸的距离     0    4     5     7     9    12      16       19   23     26     28

                   相邻的距离                  4    1      2     2     3      4        3        3      3       2

                                                    假设l = 1,h = 5, M = 4    则mid = 3, 此时去掉的石头的编号为:2,3,5,7,9  cnt = 5

                                                    按照程序,h = h - 1 = 4,此时mid = 2,去掉的石头的编号就为:2,4,9     cnt = 3(cnt<M了,

                                                    当然也有可能cnt == M,总之就是cnt > M不成立了)

                                                    也就是说,之后求得的cnt <= M恒成立, 即题目的答案不在  l 和 h 之间了(这点

                                                   之前是让我很费解的地方),更准确地说,答案就是执行这次h-1之前的h值。

                  若cnt <= M,则l = l + 1,讨论一下:若cnt < M,明显当前的mid小了,l = l + 1;若cnt == M,则去掉cnt块石头后,

                                                   剩下的石头的最小值必然是大于mid的,所以进行操作l = l + 1。

                                                   然后解决上面遇到的问题,因为h已经小于答案了,而答案就是h+1,之后继续二分cnt <= M恒成立,

                                                   l 不断自增,直到跳出循环,因为答案为h+1,我们返回 l 的值,那么while的判断条件就是 l <= h,

                                                   当 l 自增到 h + 1时就跳出循环,l == h + 1,正好就是答案。

 写了这么多,就是分析了一下二分算法执行的过程,因为以前用的二分while判断条件都是 l < h,看样子以后做二分得多注意了,

稍不注意就会有很多致命的小bug,一定要将对 l 和 h 的操作以及 while的判断条件结合起来考虑,要对二分算法进行灵活的变化,

没有一成不变的模版,具体问题具体分析。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 
 8 using namespace std;
 9 
10 int len,n,m,mid,last,cnt,l,r;
11 int d[50101];
12 int read()
13 {
14     int x=0,f=1;
15     char ch=getchar();
16     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
17     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int main()
21 {
22     len=read();n=read();m=read();    
23     for(int i=1;i<=n;i++)d[i]=read();
24     d[0]=0;d[n+1]=len;
25     sort(d+1,d+n+1);
26     l=0;r=len;
27     while(l<=r)
28     {
29         mid=(l+r)/2;
30         last=cnt=0;
31         for(int i=1;i<=n+1;i++)
32         {
33             if(d[i]-d[last]<=mid)cnt++;
34             else last=i;
35         }
36         if(cnt>m)r=mid-1;
37         else l=mid+1;
38 
39     }
40     printf("%d",l);
41     system("pause");
42     return 0;
43 }
View Code
原文地址:https://www.cnblogs.com/taojy/p/7465981.html