大致题意:青蛙通过河里的石头跳到对岸,河长L,河里有石头N块,最多只能跳M次。每个石块到岸边的距离已给出,求青蛙跳的最短距离。
解题报告:很明显河里的石头距离岸边的长度是递增的,青蛙不可能来回跳!所以可用二分来处理。刚做的时候一脸懵逼,毫无头绪,看了别人的集体思路,一点点弄明白了。。如果青蛙连两块石头间的最远距离都跳不到,它是不可能到对岸的,所以左区间应从最远距离开始。
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,d[500001];
int sum(int mid){
int i,j,k=0,y=0;
for(i=1;i<n+2;i++){
y+=d[i]-d[i-1];//y代表从岸边跳到第i个石头上所用的距离
if(y>mid){//当y大于mid时,可以mid跳到前一个石头上
y=d[i]-d[i-1];//再次从第i个开始累计
k++;// 需要跳的次数
}
}
return y>mid?1<<30:k+1;//1<<30即2^30,如果y>mid,说明最后不能跳到对岸
}
int main(){
int l,left,right,i,j,k,mid,x,s;
while(~scanf("%d%d%d",&l,&n,&m)){
for( i=1;i<=n;i++)
scanf("%d",&d[i]);
d[n+1]=l;//整条河的长度
d[0]=0;
sort(d+1,d+n+1);
for(i=1,j=0;i<n+2;i++)
if(j<d[i]-d[i-1])
j=d[i]-d[i-1];//两点之间的最远距离
left=j;right=l;//最远距离为左区间
while(left<right){//开始二分
mid=(left+right)/2;
if(sum(mid)<=m)
right=mid;// 右区间能取到mid!因为从左端起跳,临界状态
else
left=mid+1;
}
printf("%d\n",left);
}
return 0;
}