codevs 3162 抄书问题

3162 抄书问题

题目描述 Description

 

现在要把M本有顺序的书分给K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本数给同一个人抄写。现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

输入描述 Input Description

第一行两个整数M、K;(K<=M<=100)

第二行M个整数,第i个整数表示第i本书的页数。

输出描述 Output Description

共K行,每行两个正整数,第i行表示第i个人抄写的书的起始编号和终止编号。K行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。

样例输入 Sample Input

9 3

1 2 3 4 5 6 7 8 9

样例输出 Sample Output

1 5

6 7

8 9

f[i][j] 表示抄到第j本书,用了i个人的时候,抄的最多的人最少抄多少
f[i][j]=min(max( f[k-1][j-1],sum[i]-sum[k])) sum[]是维护的前缀和
求出f[n][K-1]即n本书 分给K个人抄,抄的最多的人 最少抄多少, 
 题目要求靠前的人尽可能抄的少 
那么 从后往前扫一遍,从后往前 分成一个个区间,每个区间不超过f[n][K-1]就行

#include<iostream>
#include<cstring>
using namespace std;
int n,m,a[110],sum[110],dp[110][110],cnt;
struct node{
    int l,r;
}s[110];
int main(){
    cin>>n>>m;
    if(n==0)return 0;
    memset(dp,127/3,sizeof(dp));
    for(int i=1;i<=n;i++){
        cin>>a[i];sum[i]=sum[i-1]+a[i];
        dp[i][1]=sum[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            for(int k=i;k>=1;k--){
                dp[i][j]=min(dp[i][j],max(dp[k-1][j-1],sum[i]-sum[k-1]));
            }
        }
    }
    int ans=dp[n][m];
    int sum=0,c=n;
    for(int i=n;i>=1;i--){
        sum+=a[i];
        if(sum>ans){
            s[++cnt].l=i+1;
            s[cnt].r=c;
            c=i;
            sum=a[i];
        }
    }
    if(cnt!=0){
        cout<<1<<' '<<max(1,s[cnt].l-1)<<endl;
        for(int i=cnt;i>=1;i--){
            cout<<s[i].l<<' '<<s[i].r<<endl;
        }
    }
    if(cnt==0){
        cout<<1<<' '<<n;
    }
}

 

posted @ 2017-03-01 21:52  Echo宝贝儿  阅读(326)  评论(0编辑  收藏  举报