C++跳石头题解(二分答案)

2021-03-31 21:28

阅读:612

标签:through   数组   line   函数   i+1   注意   输入输出   限制   st表   

跳石头

描述

一年一度的“跳石头”比赛又要开始了!

这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M块岩石(不能移走起点和终点的岩石)。

输入

第一行包含三个整数 L,N,M分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证L≥1 且N≥M≥0。

接下来 N行,每行一个整数,第 i行的整数Di?(0

输出

一个整数,即最短跳跃距离的最大值。

输入样例 1 

25 5 2

2

11

14

17

21

输出样例 1

4

提示

输入输出样例 1 说明:将与起点距离为 2和 14的两个岩石移走后,最短的跳跃距离为 4(从与起点距离 17 的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。

另:对于20%的数据,0 ≤ M ≤ N ≤ 100≤M≤N≤10。

对于50%的数据,0 ≤ M ≤ N ≤ 1000≤M≤N≤100。

对于 100%的数据,0 ≤ M ≤ N ≤ 50000,1 ≤ L ≤ 1000000000。

 

来源

NOIP2015 提高 t1

  先看数据范围,L居然达到了惊人的10的8次方,所以我们必须使用一种效率高、耗时少的算法——没错,就是二分(今天学的就是二分啊)。二分算法每次都会把数据分成两半,所以其时间复杂度只有logL。反观暴力枚举,其时间复杂度为L的平方。所以对于这道题来说,二分肯定是最合理的算法。

  既然要使用二分,那就必须决定要分什么。分移走的石头位置?没有任何用处。所以唯一剩下的能分的值就是本道题的答案:最短跳跃距离的最大值所以我们不妨沿着这条思路走下去。

  我们可以首先使用二分求出最短跳跃距离的最大值,然后检查其是否合法,这里可以使用一个bool函数ok来判断,二分那部分都是老套路了,bool函数ok才是二分的灵魂:

bool ok(int x)//x为通过二分算出来的最短跳跃距离的最大值
{
    int tot=0;//tot表示需要移走多少块石头
    int last=0;//last表示上一个石头的位置
    for(int i=1;i)//枚举每个石头
    {
        if(d[i]-last;//d[i]-last表示这个石头到上个没被移走的石头/起点的距离,如果距离过小,就需要移走此块石头,这样剩下的距离就是last到d[i+1]
        else last=d[i];//更新last信息,为下次循环做准备
    }
    return totm;//如果移走石头的个数小于等于m,则x的值是可取的
}

解决了ok函数,剩下的部分都是二分老套路,只有r的取值需要注意一下

完整代码+注释如下:

#includeusing namespace std;
int d[500010],L,n,m,l,r;//注意数组不要开小了

bool ok(int x)//x为通过二分算出来的最短跳跃距离的最大值
{
    int tot=0;//tot表示需要移走多少块石头
    int last=0;//last表示上一个石头的位置
    for(int i=1;i//枚举每个石头
    {
        if(d[i]-last//d[i]-last表示这个石头到上个没被移走的石头/起点的距离,如果距离过小,就需要移走此块石头,这样剩下的距离就是last到d[i+1]
        else last=d[i];//更新last信息,为下次循环做准备
    }
    return tot//如果移走石头的个数小于等于m,则x的值是可取的
}

int main()
{
    cin>>L>>n>>m;
    for(int i=1;i)
        cin>>d[i];
    r=L;//二分的右边界一定不会超过河道的长度,如果取一个极大值也没有问题,但取L能节省一些时间
    while(r-l>1)//二分求最短跳跃距离的最大值
    {
        int mid=(l+r)/2;
        if(ok(mid))
            l=mid;
        else
            r=mid;
    }
    if(!ok(r)) r=l;//扫尾工作
    coutr;//输出答案
    return 0;
}

perfect!

 

 

C++跳石头题解(二分答案)

标签:through   数组   line   函数   i+1   注意   输入输出   限制   st表   

原文地址:https://www.cnblogs.com/YC2022/p/13556203.html


评论


亲,登录后才可以留言!