洛谷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;
}