hdu4004 二分

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

}

猜你喜欢

转载自blog.csdn.net/keepcoral/article/details/80100926