复制书稿

题目描述

现在要把m本有顺序的书分给k给人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。

现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

输入输出格式

输入格式

第一行两个整数m,k;(k≤m≤500)

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

输出格式

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

输入输出样例

输入样例

9 3
1 2 3 4 5 6 7 8 9

输出样例

1 5
6 7
8 9

题解

f[i][j]表示前i个人抄j本书的最少时间
状态转移方程:f[i][j]=min{max{f[i-1][k],\(\sum_{l=k+1}^j{T_l}\),1<=k<=j-1}}
注意到题目中说要尽可能让前面的人少抄写,这里就可以采用贪心的策略,从最后一个人开始不断贪心,让其尽可能多抄写

代码

#include<cstdio>
#include<cstring>

const int MAXM=550;
int f[MAXM][MAXM],page[MAXM],sum[MAXM],m,k;

int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

inline int maxx(int x,int y){return x>y?x:y;}
inline int minn(int x,int y){return x<y?x:y;}

void dp()
{
    for(int i=2;i<=k;++i)
    {
        for(int j=1;j<=m;++j)
        {
            for(int k=1;k<=j-1;++k)
                f[i][j]=minn(f[i][j],maxx(f[i-1][k],sum[j]-sum[k]));
        }
    }
}

void print(int book,int man)
{
    if(man==0)
        return;
    if(man==1)
    {
        printf("%d %d\n",man,book);
        return;
    }
    int temp1=book,temp2=page[book];
    while(temp2+page[temp1-1]<=f[k][m])
    {
        temp2+=page[temp1-1];
        --temp1;
    }
    print(temp1-1,man-1);
    printf("%d %d\n",temp1,book);
}

int main()
{
    m=read(); k=read();
    memset(f,0x7f,sizeof(f));
    for(int i=1;i<=m;++i)
    {
        page[i]=read();
        sum[i]=sum[i-1]+page[i];
        f[1][i]=sum[i];
    }
    dp();
    print(m,k);
    return 0;
}

转载于:https://www.cnblogs.com/dustbin/p/6746370.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值