洛谷试题之跳石头

洛谷试题之跳石头

https://www.luogu.com.cn/problem/P2678

这题可以根据输出要求image-20200919095427018

最短跳跃距离的最大值,判断是要使用二分。

二分有一个模板

while(left<=right)
{
int mid=(left+right)/2;
if(check(mid))
{
  left=------
}
else{
 right=------
 }
}

这个check函数里的内容根据不同的题目不同,主要是为了判断这个中间值mid是不是符合要求,如果符合,就将左边界或者右边界根据题目的要求来进行改变。

image-20200919095757849

根据题目要求,要移走M块石头,并且不能移走起点和终点的石头,这时候我们就应该思考,通过不断的二分,判断mid是不是符合题目条件,如果两个石头之间的距离大于mid,那么就说明不需要移走石头,那么我们就跳过这块石头,跳下一块石头,如果两个石头之间的距离小于mid,那么说明我们要移走后面那块石头,同时用一个变量tot来记录移走的石头数目,当遍历了所有石头之后,如果这个tot大于题目中需要移走的石头数m,那么说明移走的石头太多了,也就是mid太大了,这时候主函数里的mid应该就要把上边界right=mid-1;反之,如果小于等于需要移走的石头数,那么说明移走的时候少了或者刚好够,这就说明mid的值太小了,我们就要在主函数里将mid的下边界left=mid+1,通过不断的二分,最终一定会趋于一个值,此时我们输出它就是本题的答案。

下面放代码WZ

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int INF= 0x3f3f3f3f;
int l, n, m;
int a[500001];

bool check(int mid)
{int tot = 0;
    int pos = 0;
    for (int i = 1; i <=n+1;i++)
    {
        if(a[i]-a[pos]>=mid)
        {
            pos = i;//跳过石头
        }
        else{
            tot++;//移走石头
        }
        
    }
    if(tot>m)
        return false;
            else{
                return true;}
}
int main()
{
    cin >> l >> n >> m;
    for (int i = 1; i <= n;i++)
    {
        cin >> a[i];
    }
    a[0] = 0;
    a[n + 1] = l;
    int left = 0;
    int right = l;
    while(left<=right)
    {
        int mid = (left + right) / 2;
        if(check(mid))//判断是否符合题意
        {
            left = mid + 1;//下边界变大
        }
        else{
            right = mid - 1;//上边界减小
        }
    }
    cout << right;;
    return 0;
}





原文地址:https://www.cnblogs.com/a821403286/p/13695164.html