动态规划(合并类)--石子合并

来源:互联网 发布:手机淘宝申请免费注册 编辑:程序博客网 时间:2024/05/17 23:04

搬上经典的合并类题目...

【动态规划】石子合并

Time Limit:30000MS  Memory Limit:65536K

Description

在一个园形操场的四周摆放N堆石子(N≤1000),现要将石子有次序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 
编一程序,读入堆数N及每堆的石子数(≤1000),选择一种合并石子的方案,使得做N-1次合并,得分的总和最小; 
例如,所示的4堆石子,每堆石子数(从最上面的一堆数起,顺时针数)依次为4594。 
则3次合并得分总和最小的方案:8+13+22=43 
得分最大的方案为:14+18+22=54 


Input

输入为两行。 
第一行为石子堆数N; 
第二行为每堆的石子数,每两个数之间用一个空格符分隔。 

Output

输出为两行 
第一行为得分最小的合并方案 
第二行为得分最大的合并方案 

Sample Input

44 5 9 4

Sample Output

4354

一开始写的时候去网上找了好多代码,交上去全是wrong answer ,后来干脆自己写了

不想废话,直接贴上AC代码吧

var n,ansmax,ansmin,j:longint;  addstone,stone:array[1..10000]of longint;  opt,optmax:array[1..1000,1..1000]of longint;procedure init;//读入+初始化var i,temp:longint;begin  readln(n);temp:=0;  for i:=1 to n do  read(stone[i]);  for i:=n+1 to 2*n-1 do  stone[i]:=stone[i-n];  for i:=1 to 2*n-1 do  begin    temp:=temp+stone[i];    addstone[i]:=temp;  end;end;function max_num(x,y:longint):longint;begin  if x>y then exit(x)  else exit(y);end;function min_num(x,y:longint):longint;begin  if x<y then exit(x)  else exit(y);end;procedure merger;  //动态规划var  i,j,k:integer;begin  for i:=1 to 2*n-1 do    opt[1,i]:=0;  for i:=2 to n do    for j:=i to 2*n-1 do      opt[i,j]:=maxlongint;  for i:=2 to n do    for j:=i to 2*n-1 do      for k:=1 to i-1 do      begin         opt[i,j]:=min_num(opt[k,j-i+k]+opt[i-k,j]+addstone[j]-addstone[j-i],opt[i,j]);         optmax[i,j]:=max_num(optmax[k,j-i+k]+optmax[i-k,j]+addstone[j]-addstone[j-i],optmax[i,j]);      end;end;begin   init;   merger; ansmin:=maxlongint;   for j:=1 to 2*n-1 do   begin     if (ansmin>opt[n,j])and(opt[n,j]<>0) then ansmin:=opt[n,j];     if (ansmax<optmax[n,j])and(optmax[n,j]<>maxlongint) then ansmax:=optmax[n,j];   end;                //搜索动态规划得出的答案   writeln(ansmin);   writeln(ansmax);   readln;readln;end.



0 0