POJ 3258

题目大意:题目很长哈,简单来说,数轴上有n个石子,第i个石头的坐标为Di,现在要从0跳到L,每次条都从一个石子跳到相邻的下一个石子。现在FJ允许你移走M个石子,问移走这M个石子后,相邻两个石子距离的最小值的最大值是多少,因为移动有很多种方法,每一种有一个最小值距离,这些最小值里面的最大值(我之所以解释最后一句,是因为我兄弟他没懂--其实不是我翻译的,嘿嘿)。
思路:在这里二分的对象当然是距离咯,我主要说下判断的条件,当你已经模拟了一个距离值后,你需要对原有的石子进行移动,因为你模拟的最小间距,所以如果两个相邻石子距离比他小,那么就应该移除后一个石子(为什么移除后一个,你可以模拟开始两石子就不满足的话,不可能移除起点吧),记录移除石子加一,然后进行下次计算,直到有个点和开始的这个点距离大于最小值(开始的点不一定是起点),记得此时更改起始点为满足时的后一个点(如不懂,可以再草稿上模拟一下过程),进行下次比较,最后比较移除的石子和实际的比较,在改变高低点的位置。
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int l,m,n,rock[50000+10];
 5 bool check(int dis)
 6 {
 7     int i=0,j,cnt=0;
 8     while(i<=n)
 9     {
10         for(j=i+1;j<=n;j++)
11         {
12             if(rock[j]-rock[i] < dis){
13                 //printf("remove %d	",rock[j]);
14                 cnt++;
15             }
16             else break;
17         }
18         i=j;
19         //printf("Now:%d
",rock[i]);
20     }
21     //printf("remove sum:%d
",cnt);
22     if(cnt <= m) return true;
23     else return false;
24 }
25 int main()
26 {
27     scanf("%d%d%d",&l,&n,&m);
28     
29     rock[0]=0;
30     for(int i=1;i<=n;i++) scanf("%d",&rock[i]);
31     sort(rock+1,rock+n+1);
32     rock[n+1]=l;
33     
34     //printf("
");for(int i=0;i<=n+1;i++) printf("%d:%d
",i,rock[i]);printf("
");
35     
36     int st=1,ed=l,mid;
37     while(st<=ed)
38     {
39         mid=st+(ed-st)/2;
40         //printf("
%d
",mid);
41         if(check(mid)) st=mid+1;
42         else ed=mid-1;
43         //printf("
");
44     }
45     printf("%d
",st-1);
46 }


原文地址:https://www.cnblogs.com/dilthey/p/6804166.html