泥豪!我是2789617221guo!欢迎来|

2789617221guo

园龄:1个月粉丝:2关注:2

2025-03-01 22:06阅读: 2评论: 0推荐: 0

洛谷P1281 书的复制 题解

本题做法

  • 贪心策略+二分答案。

思路

贪心策略:让越往前的同学抄的书尽可能少,后面的尽可能多。

使用二分答案法,详细讲解\(check\)函数的写法。

\(check\)函数

传入一个参数\(x\),代表当前二分出的预定最短复制时间。从第\(m\)本书到第1本书反向遍历,若当前同学再抄第\(i\)本书后超出\(x\),则更换下一个同学抄书。最后记得特判一个最后的同学是否能够在\(x\)时间内抄完书。


代码

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const int N = 505;
int m, k, s, p[N], r[N][2], ans;
bool check(int x) {
int now = k, cnt = 0;
for (int i = m; i >= 1; i--) {
cnt += p[i];
if (cnt > x) {
cnt = p[i];
now--;
}
if (now <= 0)
return 0;
}
if (cnt > x)
return 0;
return 1;
}
void print() {
int now = k, cnt = 0, beg = m;
for (int i = m; i >= 1; i--) {
cnt += p[i];
if (cnt > ans) {
cnt = p[i];
r[now][1] = i + 1;
r[now][2] = beg;
beg = i;
now--;
}
}
r[1][1] = 1;
r[1][2] = beg;
for (int i = 1; i <= k; i++)
cout << r[i][1] << " " << r[i][2] << endl;
}
int main() {
cin >> m >> k;
for (int i = 1; i <= m; i++) {
cin >> p[i];
s += p[i];
}
int l = 0, r = s + 1;
while (l + 1 < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
r = ans = mid;
} else
l = mid;
}
print();
return 0;
}

本文作者:2789617221guo

本文链接:https://www.cnblogs.com/2789617221guo/p/18745499

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   2789617221guo  阅读(2)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起