首页 > 代码库 > Laoj P1271 复制书稿

Laoj P1271 复制书稿

问题背景
动态规划入门-第20题
试题描述
  现在要把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

 

【分析】

典型的区间dp,三层循环轻松解决。

需要注意的是输出,要求前面的人尽量少抄于是从后往前列举,运用了贪心的思想。

 

【代码】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int m, k, a[505], sum[505], dp[505][505], maxx, b[505], c[505][505];
 5 
 6 void init() {
 7     cin >> m >> k;
 8     for (int i=1;i<=m;++i) {
 9         cin >> a[i];
10         sum[i]=sum[i-1]+a[i];
11     }
12 }
13 
14 void sovle() {
15    for (int i=1;i<=k;++i) {
16        for (int j=i;j<=m;++j) {
17            dp[i][j]=0x7fffffff;
18            for (int t=i-1;t<j;++t)
19                if (i==1)
20                    dp[i][j]=sum[j];
21                else
22                    dp[i][j]=min(dp[i][j], max(dp[i-1][t], sum[j]-sum[t]));
23        }
24    }
25    maxx=dp[k][m];
26    int t=k;
27    for (int i=m;i>0;--i) {
28        if (a[i]+b[t]>maxx)
29            t--;
30        b[t]+=a[i], c[t][++c[t][0]]=i;
31    }
32    for (int i=1;i<=k;++i)
33        cout << c[i][c[i][0]] << " " << c[i][1] << endl;
34 }
35 
36 int main() {
37     init();
38     sovle();
39 }

 

Laoj P1271 复制书稿