搬运树苗(move)
输入文件:move.in
输出文件:move.out
【问题描述】
Neyc的绿化工程正在进行,树苗已经被工人送到园区内。设计师希望将树苗种植成一个环形的绿化带,这个绿化带有n个树苗群,而每个树苗群有相同数量的树苗。但是在卸放树苗时,工人虽然按环形排列将树苗放置了n堆,但是每一个树苗群的树苗数量却没有满足要求。
于是,需要从任意一个树苗群中取任意数量的树苗搬运到相邻的树苗群,使得每个树苗群树苗的数量相等。
为了节约时间,现在需要找到一种搬运方式:搬运最少的树苗使得每一个树苗群的树苗数目相同。
当然,每个树苗群的树苗数量是已知的,分别是m1,m2……….mn,且S=m1+m2….mn必为n的倍数。
例如:n=4,每个树苗群的树苗数量分别为17 9 14 16 4,我们进行如下搬运;
(1) 树苗群1向树苗群2搬运1棵树苗;
(2) 树苗群1向树苗群5搬运4棵树苗;
(3) 树苗群3向树苗群2搬运2棵树苗;
(4) 树苗群4向树苗群5搬运4棵树苗;
搬运树苗的总数是1+4+2+4=11,并且可以证明这样的搬运方式是最佳的搬运方法。
【输入格式】
第一行正整数n(n<=10000),表示有n个树苗群;
第二行n个整数(integer范围),表示n个树苗群的树苗数量。
【输出格式】
一个正整数,表示最少搬运树苗的数量。
【样例输入】
5
17 9 14 16 4
【样例输出】
11
=================
将环拆成链......
=================
var
n:longint;
tot,ans:int64;
m:array[0..20000]of longint;
f:array[0..20000]of int64;
procedure init;
begin
assign(input,'move.in');
assign(output,'move.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure main;
var
i,j:longint;
rest:longint;
begin
readln(n);
tot:=0;
for i:=1 to n do
begin
read(m[i]);
tot:=tot+m[i];
end;
for i:=1 to n do
m[n+i]:=m[i];
tot:=tot div n;
ans:=maxlongint;
fillchar(f,sizeof(f),0);
for i:=1 to n do
begin
rest:=0;
for j:=1 to n do
begin
inc(f[i],abs(rest));
rest:=rest+m[i+j-1]-tot;
end;
if f[i]<ans then ans:=f[i];
end;
writeln(ans);
end;
begin
init;
main;
terminate;
end.