UVA714  Copying Books (抄书)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/PR_sc/article/details/77100197

题目链接
题意把一个包含m个正整数的序列划分成k 个非空的连续子序列,使得每一个正整数都恰好属于一个序列。设第i个序列的各数之和为S(i),你的任务是让所有S(i)的最大值尽量小。如果有多种解,S(1)尽量小,如果仍有多种解,S(2)尽量小。以此类推。

分析 二分查找。 在序列最大值和序列各数之和之间找一个数x,可以满足S(i)均不超过x 且序列数为k。

#include<bits/stdc++.h>
using namespace std;
int s[505],a[505],m,k,t;
int  judge(int x){
    int num=1,arr=0;
    for(int i=0;i<m;i++){
        if(a[i]+arr<=x) arr+=a[i];
        else {num++; arr=a[i];}
    }
    return num;
}
void p(long long int  n){
    long long arr=0;
    int buf=k;
    memset(s,0,sizeof(s));
    for(int i=m-1;i>=0;i--){
        if(arr+a[i]>n || i+1<buf) {
            s[i]=1;
            buf--;
            arr=a[i];
        }
        else  arr+=a[i];
    }
    for(int i=0;i<m-1;i++){
        cout<<a[i]<<" ";
        if(s[i]) cout<<"/ ";
    }
    cout<<a[m-1]<<endl;
}
int main (void){
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--){
        cin>>m>>k;
        long long  sum=0;
        int maxc=0;
        for(int i=0;i<m;i++){
            cin>>a[i];
            sum+=a[i];
            maxc=max(maxc,a[i]);
        }
        long long  low=maxc,high=sum,mid;
        while(high-low>1e-8){
            mid=(high-low)/2+low;
            if(judge(mid)<=k) high=mid;
            else low=mid+1;
        }
        p(low);
    }
    return 0;
}

总结 刚开始还被这个题目吓到了 感觉好复杂啊 想出思路后又觉得不难 hhhh

猜你喜欢

转载自blog.csdn.net/PR_sc/article/details/77100197