题意:给出n个石头,对岸距离L,可以跳跃次数m,问最短跳跃距离是多少,可以踩着石头过河。
这题目先排一下序,然后我们把起点和对岸终点同样看作一个石头,那么我们只需要对跳跃距离二分就可以了,这里需要点思考,什么时候跳跃次数最少?就是我们每次可以跳跃到的最远那个石头跳跃次数就是最短的,这样思考就可以AC了。原本以为我的代码会在恰好再第m次跳到终点时出bug,其实是不会的,因为当可以跳到的距离,我们先保存起来,直到遇到最后一个跳不到的石头,我们才去减次数,所以当最后一次跳到终点,我只是保存起来,并不会减次数,还有要注意的时,如果有两个石头的距离d>mid那么这个跳跃距离是一定跳不过的。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,L;
int a[500009];
int solve(int mid)
{
int k,i,j,d,temp,cur;
k=m;
temp=0;
cur=0;
for(i=1; i<=n+1; i++)
{
d=a[i]-a[i-1];
if(d>mid)
{
//printf("mid==%d d>mid\n",mid);
return -1;
}
//printf("mid==%d cur==%d temp==%d d==%d\n",mid,cur,temp,d);
if(mid>=cur+d)
{
temp=cur;
cur+=d;
}
else
{
k--;
i--;
cur=0;
temp=0;
}
//printf("k==%d\n",k);
if(k==0) return -1;
}
//printf("yes : mid==%d\n",mid);
return 1;
}
int main()
{
while(~scanf("%d%d%d",&L,&n,&m))
{
int i,ans;
a[0]=0;
for(i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
a[n+1]=L;
sort(a,a+n+2);
int l=1,r=50,mid;
while(l<=r)
{
mid=(l+r)/2;
// printf("l==%d r==%d\n",l,r);
int k=solve(mid);
if(k!=-1)
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
printf("%d\n",ans);
}
}