前言:
补回以前没写的书的复制。。。。
题目描述
现有n本书,编号1,2,…,n。每本Pi页。全部分给m个抄写员。每人分到顺序连续的若干本,每本只分给一人。求一种方案,使每人分到的页数和的最大值为最小。输出这个值
输入
第一行两个整数N,M(0<M<N<=3000)下一行N个数,表示书的页数.(Pi<=100000)
输出
输出最佳方案的值。
样例输入
9 3
100 200 300 400 500 600 700 800 900
样例输出
1700
思路:用DP设f[i][j] f[i][j]f[i][j]表示前i本书交由j个人抄写,需要的最短时间
动态转移方程:
f
[
i
]
[
k
]
=
m
i
n
(
m
a
x
(
f
[
j
]
[
k
−
1
]
,
t
[
i
]
−
t
[
j
]
)
,
f
[
i
]
[
k
]
)
f[i][k]=min(max(f[j][k-1],t[i]-t[j]),f[i][k])
f [ i ] [ k ] = m i n ( m a x ( f [ j ] [ k − 1 ] , t [ i ] − t [ j ] ) , f [ i ] [ k ] )
t[i]表示前i本书一共要的时间,k表示分界线。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
long long m, n, t[ 5001 ] , k, f[ 5001 ] [ 5001 ] ;
int main ( )
{
freopen ( "book.in" , "r" , stdin ) ;
freopen ( "book.out" , "w" , stdout ) ;
memset ( f, 127 / 3 , sizeof ( f) ) ;
scanf ( "%d%d" , & m, & n) ;
for ( int i= 1 ; i<= m; i++ )
{
scanf ( "%d" , & k) ;
t[ i] = t[ i- 1 ] + k;
f[ i] [ 1 ] = t[ i] ;
}
for ( int k= 1 ; k<= n; k++ )
for ( int i= 1 ; i<= m; i++ )
for ( int j= 1 ; j< i; j++ )
f[ i] [ k] = min ( max ( f[ j] [ k- 1 ] , t[ i] - t[ j] ) , f[ i] [ k] ) ;
printf ( "%d" , f[ m] [ n] ) ;
return 0 ;
}