算法:DP
这道题应该算是很简单的DP了吧,这里就简单的解释一下。
注意先排序,这样能保证最优解。
设f[i,j]表示前i根筷子配成j双的最优值,写出这个式子,DP方程立刻就可以得到:
这道题应该算是很简单的DP了吧,这里就简单的解释一下。
注意先排序,这样能保证最优解。
设f[i,j]表示前i根筷子配成j双的最优值,写出这个式子,DP方程立刻就可以得到:
f[i,j]=min(f[i-2,j-1]+sqr(a[i]-a[i-1]),f[i-1,j]),前一项表示取第i根筷子并与i-1根筷子组成一双,后一项表示不取第i双筷子,那么就从i-1根筷子组成j双筷子得来。
program NDK1111;
const
maxn=100;
maxm=50;
var
n,m:longint;
a:array [0..maxn] of longint;
f:array [-1..maxn,-1..maxm] of longint;
procedure init;
var
i:longint;
begin
readln(n,m);
inc(m,3);
for i:=1 to n do read(a[i]);
end;
procedure qsort(l,r:longint);
var
i,j,tt,t:longint;
begin
i:=l;
j:=r;
tt:=a[(l+r) shr 1];
repeat
while a[i]<tt do inc(i);
while a[j]>tt do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
procedure main;
var
i,j:longint;
begin
fillchar(f,sizeof(f),$2F);{求最小值初始化最大值。}
for i:=0 to n do f[i,0]:=0;{初始化。}
for i:=2 to n do
begin
for j:=1 to m do
begin
if i>=j*2 then{为保证配成一双的限制。}
f[i,j]:=min(f[i-2,j-1]+sqr(a[i]-a[i-1]),f[i-1,j]);
end;
end;
end;
begin
assign(input,'NDK1111.in'); reset(input);
assign(output,'NDK1111.out'); rewrite(output);
init;
qsort(1,n);
main;
if f[n,m]<>f[-1,-1] then writeln(f[n,m]) else writeln(-1);
close(input); close(output);
end.