SSL_1203 书的复制(动规练习题)

来源:互联网 发布:知乎 济南血液病医院 编辑:程序博客网 时间:2024/05/17 01:11

Description

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

Input

第一行两个整数,m,k(k<=m<=500)
第二行为m个整数,第i个数表示第i本书的页数。

Output

最短时间

Sample Input

9 31 2 3 4 5 6 7 8 9

Sample Output

17

思路

本题有两种做法,其一为二分答案,另一种为动态规划,在这里介绍的是动态规划。

用f[n][m]表示前n本书,m个人做时的最短时间。

动态转移方程

f[j][i]=min(f[j][i],max(f[l][i-1],pa[j]-pa[l]));

ps:pa为前缀和

代码

#include<cstdio>#define k freopen//文件输入输出#define r(i,a,b) for(int i=a;i<=b;i++)//循环#define pk putchar(32)//空格#define ph putchar(10)//换行using namespace std;int n,m,f[501][501],pa[501];//Prefix and 前缀和 int max(int x,int y)//最大值{    return x>y?x:y;}int min(int x,int y)//最小值{    return x<y?x:y;}void read(int &a)//输入流{    char c;int d=1,f=0;    while (c=getchar(),c<'0'||c>'9') if (c=='-') d=-1;f=f*10+c-48;//因为这个卡了半天,书本页数竟然有负数。。。    while (c=getchar(),c>='0'&&c<='9') f=f*10+c-48;    a=d*f;return;}void write(int x)//输出流{    if(x)write(x/10);else return;    putchar(x%10+48);}void print(int i,int j)//输出每个人抄写的书本数,洛谷上也有这道题,输出的就是每个人抄第几本到第几本,https://www.luogu.org/problemnew/show/1281{    int t,x;    if (i<=0) return;    if (!j) return;    if(j==1)     {write(1);pk;write(i);ph;return;}    t=i;x=pa[i]-pa[i-1];    while (x+pa[t-1]-pa[t-2]<=f[n][m]&&t>1)    {     x=x+pa[t-1]-pa[t-2];     t--;    }    print(t-1,j-1);    write(t);pk;write(i);if (i!=n) ph;}int main(){    read(n);read(m);int x;    r(i,0,500)     r(j,0,500)      f[i][j]=2147483647;//初值    r(i,1,n) {read(x);pa[i]=pa[i-1]+x;f[i][1]=pa[i];}//第一个人抄的就是前缀和    r(i,2,m)     r(j,1,n)      r(l,1,j-1)       f[j][i]=min(f[j][i],max(f[l][i-1],pa[j]-pa[l]));//动态转移  //print(n,m);  write(f[n][m]);//输出}


原创粉丝点击