首页 > 代码库 > codevs 3162 抄书问题

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;    }}

 

codevs 3162 抄书问题