河的长度为L, 有n个石头,最多跳m次,求青蛙最少至少能够跳多远的最小值。
二分,去年学过,好像也写过,今年还是不会,惭愧。
在两个石头的最大值和河的宽度L之间二分,每一次判断在当前mid下,可不可以到达对岸
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int a[500005],b[500005];
int main()
{
int i,L,n,m;
int mid,max_,le,ri;
while(scanf("%d%d%d",&L,&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
a[n+1]=L;
a[0]=0;
sort(a,a+n+2); /// 数据不是依次给的 所以要先排序
max_=0; /// 两个石头的最大距离
for(i=1;i<=n+1;i++){
b[i]=a[i]-a[i-1]; ///求从开始的岸边开始,每连个点的距离,一共有n+1个
if(max_<b[i])
max_=b[i];
}
if(m>n){ /// if m>n 即每次都依次跳到下一个石头就可以保证到达对岸, 此时输出max_
printf("%d\n",max_);
continue;
}
le=max_;
ri=L;
int cnt=0,t;
while(le<=ri){ /// 二分
t=mid=(le+ri)/2;///步数
cnt=0; /// 走的
i=1; /// 走到第n个石头
while(cnt<=m&&i<=n+1){ /// 能力为mid时,判断可不可以跳过
t=mid;
while(i<=n+1&&b[i]<=t) /// 一次最多跳到哪个石头上,
t-=b[i++];
cnt++;
}
if(cnt<=m&&i>n+1) ri=mid-1; /// 跳过了 ,说明mid大了,将ri=mid-1;
else le=mid+1;
}
printf("%d\n",le);
}
return 0;
}