Description
现在要把
m
m
m本有顺序的书分给
k
k
k个人复制(抄写),每个人的抄写速度都一样,一本书不允许分给两个或两个以上的人抄写,分给每个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。
现在请你设计一种方案,使得复制时间最短。复制时间为抄写最多的人用去的时间。
Input
第一行两个整数,
m
,
k
(
k
<
=
m
<
=
500
)
m,k(k<=m<=500)
m,k(k<=m<=500)
第二行为
m
m
m个整数,第
i
i
i个数表示第
i
i
i本书的页数。
Output
最短时间
Sample Input
9 3
1 2 3 4 5 6 7 8 9
Sample Output
17
Hint
GDOI
解题思路
好的,又是道DP
题目大意:把书分成
k
k
k段,保证每段的时间和最小,输出和的最大值
设
f
[
i
,
j
]
f[i,j]
f[i,j]为第
j
j
j个人抄写到第
i
i
i本书
取一个断点
g
g
g
(
j
−
1
<
=
g
<
=
i
)
(j-1<=g<=i)
(j−1<=g<=i)
- 前 j − 1 j-1 j−1个人抄写到第 g g g本书,费用为 f [ g , j − 1 ] f[g,j-1] f[g,j−1]
- 当前到第 j j j个人,费用为 s u m [ g + 1 , i ] sum[g+1,i] sum[g+1,i] ( s u m sum sum是前缀和)
取个
m
a
x
max
max,就是
m
a
x
(
f
[
k
]
[
j
−
1
]
,
s
u
m
[
k
+
1
]
[
i
]
)
max(f[k][j-1],sum[k+1][i])
max(f[k][j−1],sum[k+1][i])
因为要保证最小,还要加个
m
i
n
min
min,就是
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
m
a
x
(
f
[
k
]
[
j
−
1
]
,
s
u
m
[
k
+
1
]
[
i
]
)
)
f[i][j]=min(f[i][j],max(f[k][j-1],sum[k+1][i]))
f[i][j]=min(f[i][j],max(f[k][j−1],sum[k+1][i]))
(啊!我看不懂!)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF=0x7777777;
int f[600][600],n,m,a[600],sum[600][600];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=1;j<=i;j++)
sum[j][i]=sum[j][i-1]+a[i];//预处理前缀和
}
memset(f,INF,sizeof(f));//因为f要取min,so,把f赋成无限大
f[0][0]=0;//初始值
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=j-1;k<i;k++)
f[i][j]=min(f[i][j],max(f[k][j-1],sum[k+1][i]));
}
}
printf("%d",f[n][m]);
}