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