题目见:http://www.rqnoj.cn/Problem_349.html
分析
所求为所需最小时间,而最短的时间又决定于最慢的人。对一个区间,分出j-1份(j个人)可以等价于,将区间分成两部分,一部分由j-1个人完成,另一部分有一个人完成,那么一定存在一个中间的位置取得最优值。据此可以写出转移方程f[i,j]:=max(f[k-1,j-1],s[i]-s[k-1])。其中,f[i,j]表示到第i本书分给j个人的最优值,s表示区间和。
由于本题对方案有特殊要求,所以不能简单的在动规过程中记录方案,动规中方案的记录,只是当前区间的最优方案,并不是满足题意的方案,所以必须从后向前去推,是每个人做的最多。
code
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
book.pasprogram haha;
var
n,m,i,j,k,tot : longint;
a,s,final : array[0.. 500] of longint;
f,ans : array[0..501,0..501] of longint;
procedure init;
begin
fillchar(f,sizeof(f),126);
readln(n,m);
for i:=1 to n do
begin
read(a[i]);
s[i]:=s[i-1]+a[i];
f[i,1]:=s[i];
end;
end; { init }
function max(x,y : longint):longint;
begin
if x>y then
exit(x)
else
exit(y);
end; { max }
procedure work;
var
t : longint;
begin
for i:=1 to n do
for j:=2 to m do
for k:=j to i do
begin
t:=max(f[k-1,j-1],s[i]-s[k-1]);
if t<f[i,j] then
f[i,j]:=t;
end;
end; { work }
procedure deal;
var
t,k,temp : longint;
begin
k:=n;
temp:=m;
final[temp+1]:=n;
while temp>0 do
begin
t:=0;
while (t+a[k]<=f[n,m]) and (k>0) do
begin
inc(t,a[k]);
dec(k);
end;
final[temp]:=k;
dec(temp);
end;
end; { deal }
begin
assign(input,'book.in'); reset(input);
assign(output,'book.out'); rewrite(output);
init;
work;
deal;
for i:=1 to m do
writeln(final[i]+1,' ',final[i+1]);
close(input);
close(output);
end.