zoukankan      html  css  js  c++  java
  • 洛谷P2678 跳石头 题解 二分答案

    题目链接:https://www.luogu.com.cn/problem/P2678

    首先,如果告诉了我们最短跳跃距离为 len,我们是不能能够确定最少需要移除的石头数?
    我们可以将 Di 数组从小到大排序,一开始我在 0 位置,然后我从 1 到 n 去遍历坐标 i,如果 Di 和我当前位置的距离小于 len,那么为了保证“最短跳跃距离≥len”这个条件,我必须移除第 i 块岩石;否则(距离≥len),我得跳到第 i 块岩石(基于贪心思想:一方面当前少移除一块岩石,另一方面最大化接下来岩石的距离范围)。
    于是乎,这样一轮循环之后我就能确定我最少需要移除的岩石数,只要这个数不超过 M,那么 len 这个最短跳跃距离就是合法的。

    然后我可以开一个 bool check(int len) 函数用于判断 len 作为最短跳跃距离是否合法。
    如果合法 check(len) 会返回 true;不合法 check(len) 会返回 false。

    然后我们可以以 len 为自变量,以 check(len) 的结果为应变量进行二分。我们可以发现,存在一个 X,使得当 len≤X时 check(len) 均返回 true;当 len≥X+1 时 check(len) 均返回 false。这个 X 即为我们的答案。

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    int L, n, m, d[50050];
    bool check(int len) {
        int p = 0, cnt = 0;
        for (int i = 1; i <= n+1; i ++) {
            if (d[i]-d[p] < len) {
                cnt ++;
                if (cnt > m) return false;
            }
            else p = i;
        }
        return true;
    }
    int main() {
        cin >> L >> n >> m;
        for (int i = 1; i <= n; i ++) cin >> d[i];
        sort(d+1, d+1+n);
        d[0] = 0;
        d[n+1] = L;
        int l = 0, r = L, res;
        while (l <= r) {
            int mid = (l + r)/2;
            if (check(mid)) {
                res = mid;
                l = mid+1;
            }
            else r = mid-1;
        }
        cout << res << endl;
        return 0;
    }
    
  • 相关阅读:
    乱谈服务器编程
    set global slow_query_log引起的MySQL死锁
    一个由string使用不当产生的问题
    Hbase初体验
    浅谈SQLite——查询处理及优化
    ACID、Data Replication、CAP与BASE
    libevent源码分析
    浅析Linux Native AIO的实现
    vim7.2中文乱码解决方法
    伸展树的点点滴滴
  • 原文地址:https://www.cnblogs.com/quanjun/p/12562244.html
Copyright © 2011-2022 走看看