NOIP2015跳石头【二分答案(最小值最大化) | 贪心】

519. 跳石头 - AcWing题库

组委会已经选择好了两块岩石作为比赛起点 0 和终点 L 。 

在起点和终点之间,有 NN 块岩石(不含起点和终点的岩石)。

在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。

由于预算限制,组委会至多从起点和终点之间移走 MM 块岩石(不能移走起点和终点的岩石)。

如果长度 Len 可以满足,那么当长度小于 Len 时也可以满足,所以我们可以二分出最大的 Len。

首先验证答案具有单调性:拿走的石头越多,最短跳跃距离越大,这就叫答案的单调性。

然后进行实现。我们假设最短跳跃距离为mid,接着我们写一个check函数,判断一下这个mid是否合法如果合法,就尝试找一找有没有一个值比mid更大(l=mid),如果不合法,就把mid减小(r=mid-1)。

check函数:我们遍历一遍每一块石头,累计出有多少块石头之间的间隔<=mid,如果超过m个,就不合法,如果小于等于m,就合法

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int n, m, L;
vector<int> d;
bool check(int mx)
{
    int cnt = 0, last = 0;
    for (int i = 0; i <= n; i ++ ) {
        if(d[i] - last < mx) cnt ++;
        else last = d[i];
    }   
    return cnt <= m;
}
int main(){
    //std::ios::sync_with_stdio(false);
    //std::cin.tie(nullptr);
    cin >> L >> n >> m;
    d.resize(n);
    for (int i = 0; i < n; i ++ ) {
        cin >> d[i];
    }
    d.push_back(L);
    int l = 0, r = 1e9;
    while(l < r) {
        int mid = l + r + 1 >> 1;
        if(check(mid)) l = mid;
        else r = mid - 1;
    }
    cout << l << '\n';
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值