您的位置:首页 > 其它

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

2015-05-17 11:06 288 查看
搬上经典的合并类题目...

【动态规划】石子合并
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

4
4 5 9 4


Sample Output

43
54


一开始写的时候去网上找了好多代码,交上去全是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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息