UVa 714 - Copying Books

题目大意:

要抄N本书,编号为1,2,3…N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的。每个抄写员的速度是相同的,求所有书抄完所用的最少时间的分配方案。

Sample Input
2
9 3
100 200 300 400 500 600 700 800 900
5 4
100 100 100 100 100
Sample Output
100 200 300 400 500 / 600 700 / 800 900
100 / 100 / 100 / 100 100

分析与总结:

所化的总时间取决于所有抄写员中任务最多的那个,是经典的最大值最小化问题。在这题中,需要注意的是求和时用32位int可能会溢出,所以要用long long.

#include<cstdio>
#include<cstring>
#define MAXN 505
using namespace std;
int m, k;
long long arr[MAXN], sum, min, ans;
bool vis[MAXN];
 
int divide(long long M){
    memset(vis, 0, sizeof(vis));
    int cnt=0;//用于记录当前方案需要的人数
    int pos=m-1;//从后往前分解
    while(pos>=0){
        long long sum=0;
        while(pos>=0 && sum+arr[pos]<=M){
            sum += arr[pos];
            --pos;
        }
        if(pos>=0) vis[pos] = true;
        ++cnt;
    }
    return cnt;
}
 
long long binary(){
    long long left=min, right=sum, mid;//left用于记录最少,right用于记录最多所花的时间,mid则采用二分法来计算花时间最少的人
    while(left<right){
        mid = (left+right)>>1;
        if(divide(mid)<=k) 
            right=mid;
        else 
            left=mid+1;
    }
    return right;
}
 
void output(){
    int cnt=divide(ans);
    for(int i=0; i<m-1&&cnt<k; ++i)if(!vis[i]){
        vis[i]=true;
        ++cnt;
    } 
    for(int i=0; i<m; ++i){
        if(i) printf(" %lld",arr[i]);
        else printf("%lld",arr[i]);
        if(vis[i]){
            printf(" /");
        }
    }
    puts("");
}
 
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&m,&k);
        sum=0;  min=0;
        for(int i=0; i<m; ++i){
            scanf("%lld",&arr[i]);
            sum += arr[i];
            if(arr[i]>min) min=arr[i];
            //这里需要和binary()函数一起分析,min是指一个工人最少看的页数,不可能少于这个数,因为此题算的是所有人中花的时间最多的人
        }
        ans=binary();
        output();
    }
    return 0;
}

发布了29 篇原创文章 · 获赞 2 · 访问量 919

猜你喜欢

转载自blog.csdn.net/qq_44954571/article/details/105141810