筷子(NDK1111)

算法: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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值