编程语言
首页 > 编程语言> > C++-跳石头 解题思路

C++-跳石头 解题思路

作者:互联网

【Horn Studio】编程专栏: 抢气球  解题思路

题目

题目描述

一年一度的“跳石头”比赛又要开始了!
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有NN块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走MM块岩石(不能移走起点和终点的岩石)。

输入

第一行包含三个整数L,M,NL,M,N,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会最多移走的岩石数。保证L≥1L≥1且N≥M≥0N≥M≥0 。
接下来NN行,每行一个整数,第ii行的整数DiDi,表示第ii块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个出现在同一个位置。

输出

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

样例输入 复制

25 5 2 
2
11
14
17 
21

样例输出 复制

4

提示

对于20%的数据,
0≤M≤N≤100≤M≤N≤10
对于50%的数据,
0≤M≤N≤1000≤M≤N≤100
对于100%的数据,
0≤M≤N≤50,000,1≤L≤1,000,000,00000≤M≤N≤50,000,1≤L≤1,000,000,0000

来源

思路

这道题跟二分一样,从起点出发,先选定一段距离mid,若前面的石头B与你所站着的石头A的距离小于mid,就把B搬掉,记录一下;如果不,就把B留下,再跳到石头B上。照这个步骤多次循环后,如果搬掉的石头多了,就把距离mid定小点;如果少了,就把mid定大点。,很简单。直接考虑问题比较困难。我们首先考虑另一个问题,如果给定一个距离d,问至少要移走多少石头才能满足石头之间的最小距离不小于d?对于这个问题,答案就很简单了。从左岸开始,移走它小于d的所有石头,再往后跳一步,循环往复。就解决了!

我们同样需要一个判断,大概就是如下:

bool check(int x)
{
    int last = 0, cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] - last < x)
            cnt++;
        else
            last = a[i];
    }
    if (cnt > m)
        return false;
    return true;
}

代码

#include <bits/stdc++.h>
using namespace std;
int a[50010], n, m, L, ans;

bool check(int x)
{
    int last = 0, cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] - last < x)
            cnt++;
        else
            last = a[i];
    }
    if (cnt > m)
        return false;
    return true;
}

int main()
{
    cin >> L >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    a[n + 1] = L;
    int l = 0, r = L;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            ans = mid;
            l = mid + 1;
        } else
            r = mid - 1;
    }
    cout << ans;

    return 0;
}

彩蛋

……这是哪?

 

标签:移走,int,岩石,C++,解题,000,终点,思路,起点
来源: https://www.cnblogs.com/Kelwen/p/Horn_Studio_CodeBlock_Half_8_end.html