题意:给出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); } }