codevs动态规划 能量项链

Mars星球上,每个Mars人都随身佩带着一串能量项链。在项链上有N颗能量珠。能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数。并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量。如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m*r*n(Mars单位),新产生的珠子的头标记为m,尾标记为n

需要时,Mars人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。显然,不同的聚合顺序得到的总能量是不同的,请你设计一个聚合顺序,使一串项链释放出的总能量最大。

例如:设N=44颗珠子的头标记与尾标记依次为(23) (35) (510) (102)。我们用记号⊕表示两颗珠子的聚合操作,(jk)表示第jk两颗珠子聚合后所释放的能量。则第41两颗珠子聚合后释放的能量为:

(41)=10*2*3=60

这一串项链可以得到最优值的一个聚合顺序所释放的总能量为

((41)2)3=10*2*3+10*3*5+10*5*10=710

分析:题目中的能量其实可以分解成若干个小球,其实就是通过若干次动态规划求出相应的小球最后再将能量值进行相乘,求小球的能量的动态规划很常规的划分规划,就不多做解释了。

动态转移方程:f[j,l]:=max(f[j,k-1]+f[k,l]+a[j]*a[l+1]*a[k],f[j,l]);

const
  maxn=200;


var
  f:array[1..maxn,1..maxn] of int64;
  a:array[1..maxn] of longint;
  n,max:longint;


procedure init;
var
  i:longint;
begin
  readln(n);
  for i:=1 to n do
    read(a[i]);
  a[n+1]:=a[1];
end;


procedure work;
var
  i,j,k,l:longint;
begin
  for i:=1 to n-1 do
    for j:=1 to n-i do
      begin
        l:=j+i;
        f[j,l]:=0;
        for k:=j+1 to l do
          if f[j,k-1]+f[k,l]+a[j]*a[l+1]*a[k]>f[j,l] then
            f[j,l]:=f[j,k-1]+f[k,l]+a[j]*a[l+1]*a[k];
      end;
  if f[1,n]>max then
    max:=f[1,n];
end;


procedure main;
var
  i,j:longint;
begin
  for i:=1 to n do
    begin
      fillchar(f,sizeof(f),0);
      work;
      for j:=1 to n do
        a[j]:=a[j+1];
      a[n+1]:=a[1];
    end;
end;


begin
  init;
  main;
  write(max);
end.

你可能感兴趣的:(动态规划)