zoukankan      html  css  js  c++  java
  • 洛谷P1182 数列分段 Section II 题解 二分答案

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

    解题思路:
    二分答案。
    check(num)用于判断每段不超过num的情况是否存在。
    然后二分答案。


    2020-3-24 思路补充:

    首先,我们可以编写一个 bool check(int len) 函数,该函数用于验证当每段的最大值为 len 时是否满足条件。
    怎么验证呢?
    首先,如果存在某一个整数 Ai ≥ len,那么肯定不满足条件;
    其次,我假设一开始 A1 在第1段,然后我去看看 A2 和 A1 合到一起是不是 ≤ len,如果是的话就把 A2 和 A1 合道一起,如果不行则将 A2 放到第2段;然后 A3 也看能不能和 A2 放在同一段,如果可以就放在同一段,如果不行 A3 就再开一段,……,当 AN判断结束的时候,我们可以看看总共分了多少段。

    如果总共分的段数 ≤ M,说明此方案可行,check(len) 返回 true;否则,此方案不可行,check(len) 返回 false。

    然后我们在此基础上,以 len 作为自变量,以 check(len) 的结果作为应变量,我们可以发现存在一个点 X0,使得当 len<X0 时,check(len) 都为 false;当 len>=X0 时,check(len) 都为 true。我们可以通过二分找到这个 X0,即为我们要求的答案。


    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    int n, m, a[maxn], sum;
    bool check(int num) {
        int cnt = 1, tot = 0;
        for (int i = 0; i < n; i ++) {
            if (tot + a[i] <= num) tot += a[i];
            else if (a[i] > num) return false;
            else {
                tot = a[i];
                cnt ++;
                if (cnt > m) return false;
            }
        }
        return true;
    }
    int main() {
        cin >> n >> m;
        int L = 0, R = 0, res;
        for (int i = 0; i < n; i ++) {
            cin >> a[i];
            R += a[i];
        }
        while (L <= R) {
            int mid = (L + R) / 2;
            if (check(mid)) {
                res = mid;
                R = mid - 1;
            }
            else L = mid + 1;
        }
        cout << res << endl;
        return 0;
    }
    
  • 相关阅读:
    JDK1.8源码之HashMap(一)——实现原理、查找及遍历
    JDK1.8源码之ArrayList
    03、Swagger2和Springmvc整合详细记录(爬坑记录)
    02、Java的lambda表达式和JavaScript的箭头函数
    Java-IO流之输入输出流基础示例
    JDBC API 事务的实践
    JDBC API 可滚动可编辑的结果集
    Java虚拟机----垃圾回收与内存分配
    Java数据库连接与查询
    Java虚拟机-对象的创建和访问
  • 原文地址:https://www.cnblogs.com/quanjun/p/12312974.html
Copyright © 2011-2022 走看看