区间DP:石子归并

百般思念 提交于 2020-01-26 00:48:21
题目描述 
Description

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

输入描述 Input Description

第一行一个整数n(n<=100)

第二行n个整数w1,w2...wn  (wi <= 100)

输出描述 Output Description

一个整数表示最小合并代价

样例输入 Sample Input

4

4 1 1 4

样例输出 
Sample Output
18这道题可以轻松地找出状态转移方程f[i,j]:=max{f[i,k]+f[k+1,j]}+sum[i,j];但问题是如何递推是个问题,1:若正推,for i:=1 to n do              for j:=i to n do   这样的话,递推顺序为(1,1),(1,2),(1,3),(1,4),(2,2).....   中间还有未求的量。2:若逆推,顺序为(n,n),(n-1,n-1),(n-1,n),(n-2,n-2)....。故应逆推。还有一点要注意,就是当前所求的区间的前趋i,后趋j,和中间变量k有(i=j-1=k)时f[i,j]:=stone[i]+stone[j];
var num:longint;    stone:array[1..100]of integer;    i,j,k,l,n,max:longint;    sum:array[1..100,1..100]of longint;    f:array[1..100,1..100]of longint;

begin fillchar(stone,sizeof(stone),0);      fillchar(sum,sizeof(sum),0);      fillchar(f,sizeof(f),$7F);      readln(n);      for i:=1 to n do          read(stone[i]);      for i:=1 to n do          for j:=i to n do              for k:=i to j do                  sum[i,j]:=sum[i,j]+stone[k];      for i:=1 to n do          f[i,i]:=0;      for i:=n downto 1 do          for j:=i to n do              for k:=i to j-1 do                  if (i=k)and(k=j-1)                     then begin if f[i,j]>f[i,k]+f[k+1,j]+sum[i,j]                                   then f[i,j]:=stone[i]+stone[j];                          end                     else begin if f[i,j]>f[i,k]+f[k+1,j]+sum[i,j]                                   then f[i,j]:=f[i,k]+f[k+1,j]+sum[i,j];                          end;      writeln(f[1,n]);end.
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!