hdu The Frog's Games(二分枚举)

60 篇文章 1 订阅
31 篇文章 0 订阅
The Frog's Games

题目大意: 长为L的河流,中间有n个石头,告诉你石头的位置,青蛙的跳跃能力至少为多少时最终跳 m次能跳过终点
思路: 因为青蛙的跳跃能力越强需要的次数就越少,因此青蛙的跳跃能力有单调性,所以二分枚举青蛙的跳跃能力,再判断在这个能力下是否能够跳过去。这个用贪心解决,每次在这个能力下尽可能跳到远的石头上,最后看m次是否跳到了对岸。

方法一(利用vector容器):
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
int l,n,m;
vector<int>s;
bool check(int dis)
{
    int sum=0,i,j=0,cnt=0;
    int k=s.size();
    for(i=0; i<m; i++)
    {
        while(j<k&&s[j]<=sum+dis)//如果如果青蛙能跳过此石头s[j]的位置,就记录下此石头的位置,并继续检测青蛙是否能跳过下一个石头
        {
            cnt=s[j];//记录走过的石头的位置
            j++;
        }
        sum=cnt;//记录每一步跳到的位置
    }
    if(sum>=l)//如果青蛙能过在m步内跳过终点,则此跳跃能力合格
        return 1;
    return 0;
}
int main()
{
    while(~scanf("%d%d%d",&l,&n,&m))
    {
        int i,k;
        s.clear();
        s.push_back(0);
        for(i=0; i<n; i++)
        {
            scanf("%d",&k);
            s.push_back(k);
        }
        s.push_back(l);
        sort(s.begin(),s.end());
        int x=0,y=l,mid;
        while(x<y)
        {
            mid=x+(y-x)/2;
            if(check(mid))
                y=mid;
            else
                x=mid+1;
        }
        printf("%d\n",x);
    }
    return 0;
}
ps:此法核心就是判断在m步内能否跳过终点。
方法二(普通数组):
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=500050;
int s[N];
int l,n,m;
bool check(int dis)
{
    if(dis*m<l)//如果m步还不能跳到终点,则此跳跃距离不合格,先判断可以减少时间复杂度
        return 0;
    int i=1,j=0,step=0;
    while(i<=n+1)
    {
        step++;//记录步数
        if(dis<s[i]-s[j])//如果跳跃距离小于两块石头的距离,则此跳跃距离不合格
            return 0;
        while(i<=n+1&&dis>=s[i]-s[j])//找到在当前跳跃距离下所能跳跃的最大距离
            i++;
        j=i-1;//保留当前走到的位置
    }
    if(step>m)//如果步数大于m,即此跳跃距离不合格
        return 0;
    return 1;
}
int main()
{
    while(~scanf("%d%d%d",&l,&n,&m))
    {
        memset(s,0,sizeof(s));
        int i;
        s[0]=0;
        for(i=1;i<=n;i++)
            scanf("%d",&s[i]);
        s[n+1]=l;
        sort(s,s+n+1);//对石头的位置排序
        int x=0,y=l,mid;
        while(x<=y)
        {
            mid=x+(y-x)/2;
            if(check(mid))
                y=mid-1;
            else
                x=mid+1;
        }
        printf("%d\n",x);
    }
    return 0;
}
ps:此法的核心是判断在走过终点时所用步数是否超过m步。

小结:二分枚举的题的特点都是是否单调连续,如果题目有这个特点的话,那么就可以考虑通过二分的思想来求解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值