TYVJ1191(迎春舞会之三人组舞)

算法:DP
看起来短短的不到50行的代码,但是从构建DP方程来说,本题确实属于难题。
DP方程:f[i,j]:=min(f[i,j],min(f[i-1,j],f[i-2,j-1]+sqr(a[i-1]-a[i])));

思路是只分站在两边的人,而站在中间的人不参加计算,同时要选最小的一定是选邻近的,因为邻近的差值最小。

program P1191;

const
  maxn=5000;
  maxm=1000;

var
  a:array [0..maxn] of longint;
  f:array [0..maxn,0..maxm] of longint;{f[i,j]表示前i个人分成j组的最小残废程度。目标就是f[n,m]。}
  m,n:longint;
  
procedure init;
var
  i:longint;
begin
  readln(m,n);
  for i:=n downto 1 do read(a[i]);{倒着记录,即a[1]最大,a[n]最小。}
  fillchar(f,sizeof(f),100);{求最小,初始化成最大。}
  for i:=1 to n do f[i,0]:=0;{前i个数分成0组的最小残废程度肯定是0。}
  f[3,1]:=sqr(a[3]-a[2]);{这个手工计算一下,前3个数分成1组。}
end;

function min(x,y:longint):longint;
begin
  if x>y then exit(y) else exit(x);
end;

procedure main;
var
  i,j:longint;
begin
  for i:=4 to n do{3的算过了,从4开始算。}
    begin
      for j:=1 to m do
        begin
          if i>=3*j then{限制条件,即人数必须大于等于当前要分的组数中的人数。}
            begin
              f[i,j]:=min(f[i,j],min(f[i-1,j],f[i-2,j-1]+sqr(a[i]-a[i-1])));
            end;
        end;
    end;
end;

begin
  assign(input,'P1191.in'); reset(input);
  assign(output,'P1191.out'); rewrite(output);

  init;
  main;
  writeln(f[n,m]);
  
  close(input); close(output);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值