题目大意:题目很长哈,简单来说,数轴上有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 }