【poj 1505】 Copying Books

题意:

现在要把m本有顺序的书分给k个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三和第四本书给同一个人抄写。现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。如果有多组解的话先要保证第一个人抄的尽量少,若仍有多组解,要先保证第二个人抄的尽量少,以此类推。要注意一下,保证前面的尽量小,前面的也要有的抄。

思路:

经典的二分答案+验证的题目。分析题目的单调性,设抄写页数最多的人用去的时间为x,考虑x很小的时候,能写完的书的数量y一定很小,随着x变大,每个人分到的书的数量会增加,能完成的书的总量就会增加,所以x递增时,y递增,满足单调性。然后,二分枚举x,找到最小的x,使y >= m 成立。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll inf = 1e17;
ll a1[510], is[510];
int n, m;
bool check(ll val){
    ll s = 0, cnt = 1;
    for(int i = 1; i <= n; i ++){
        if(a1[i] > val) return false;
        if(s+a1[i] <= val) s += a1[i];
        else cnt ++, s = a1[i];
    }
    return cnt <= m;
}
int main(){
    int T;
    scanf("%d", &T);
    while(T --){
        memset(is, 0, sizeof is);
        ll l = inf, r = 0, ans = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i ++) 
            scanf("%d", &a1[i]), l = min(l, a1[i]), r += a1[i];
        while(l <= r){
            ll mid = (l+r)>>1;
            if(check(mid)) ans = mid, r = mid - 1;
            else l = mid + 1;
        }
        ll s = 0;
        int now = m;
        is[0] = 1;
        for(int i = n; i >= 1; i --){
            if(i >= now && a1[i]+s <= ans) s += a1[i];
            else s = a1[i], now --;
            is[i] = now;
        }
        for(int i = 1; i <= n; i ++){
            if(is[i] != is[i-1]) printf("/ ");
            printf("%I64d ", a1[i]);
        }
        printf("\n");
    }
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值