合并类动态规划——石子合并(洛谷1880)

一世执手 提交于 2019-12-23 13:41:23
 题目描述 Description
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
 输入输出格式 Input/output
输入格式:
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式:
输出共2行,第1行为最小得分,第2行为最大得分.
 输入输出样例 Sample input/output
样例测试点#1
输入样例: 

4
4 5 9 4

输出样例:

43

54

来源:NOI 1996

代码:

var n,i,j,k,l,minf,maxf:longint;
    a,s:array[0..300] of longint;
    f:array[1..300,1..300] of longint;
function min(x,y:longint):longint;
begin
  if x<y then exit(x) else exit(y);
end;
function max(x,y:longint):longint;
begin
  if x>y then exit(x) else exit(y);
end;
begin
  readln(n);
  for i:=1 to n do
    begin
      read(a[i]);
      a[i+n]:=a[i];
    end;


  for i:=1 to 2*n-1 do
       s[i]:=s[i-1]+a[i];   
  for l:=2 to n do           //枚举可能的长度
    for i:=1 to 2*n-l do     //环形扩展到链
      begin
        j:=i+l-1;
        f[i,j]:=maxlongint;
        for k:=i to j-1 do
          f[i,j]:=min(f[i,j], f[i,k]+f[k+1,j]+s[j]-s[i-1]);
      end;
  minf:=maxlongint;
  for i:=1 to n do minf:=min(minf,f[i,i+n-1]); //求出最小的值

  fillchar(f,sizeof(f),0);
  for l:=2 to n do
    for i:=1 to 2*n-1 do
      begin
        j:=i+l-1;
        f[i,j]:=0;
        for k:=i to j-1 do
          f[i,j]:=max(f[i,j], f[i,k]+f[k+1,j]+s[j]-s[i-1]);
      end;
  maxf:=0;
  for i:=1 to n do maxf:=max(maxf,f[i,i+n-1]);

  writeln(minf);
  writeln(maxf);
end.

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!