洛谷P1281 书的复制 题解 二分答案

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

解题思路:

二分答案。

check(num) 用于判断每个人分配 num 也的方案是否可行,然后二分答案。
solve(num) 函数,用于确保尽可能让前面的人少抄写。其实现给予贪心思想是:尽可能地让后面的人多抄写,则前面的人就能少抄写。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 550;
int m, k;
long long a[maxn];
bool check(long long num) {
    int id = 1;
    long long tot = 0;
    for (int i = 0; i < m; i ++) {
        if (tot+a[i] <= num) tot += a[i];
        else if (num < a[i]) return false;
        else {
            id ++;
            tot = a[i];
            if (id > k) return false;
        }
    }
    return true;
}
vector<pair<int, int> > res;
void solve(int num) {
    int j = m-1;
    long long tot = 0;
    for (int i = m-1; i >= 0; i --) {
        if (tot+a[i] <= num) tot += a[i];
        else {
            res.push_back(make_pair(i+1, j));
            j = i;
            tot = a[i];
        }
    }
    res.push_back(make_pair(0, j));
    // 因为保证所有人有活可干,所以这里不额外处理了
    for (int i = k-1; i >= 0; i --) {
        cout << res[i].first+1 << " " << res[i].second+1 << endl;
    }
}
int main() {
    cin >> m >> k;
    long long L = 0, R = 0, res;
    for (int i = 0; i < m; i ++) {
        cin >> a[i];
        R += a[i];
    }
    while (L <= R) {
        long long mid = (L + R)/2;
        if (check(mid)) {
            res = mid;
            R = mid-1;
        }
        else L = mid+1;
    }
    solve(res);
    return 0;
}
posted @ 2020-02-07 11:46  quanjun  阅读(134)  评论(0编辑  收藏  举报