您的位置:首页 > 其它

【区间动规】【记忆化搜索】[NOI1995]石子合并

2012-08-19 17:45 330 查看

题目:[NOI1995]石子合并 rqnoj490

题目描述

在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

输入格式

数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出格式

输出共2行,第1行为最小得分,第2行为最大得分.

样例输入

4
4 4 5 9

样例输出

43
54

动规 f[i,j]表示区间[i,j]

  f[i,j]=max{f[i,j],f[i,k]+f[k+1,j]+i 到 j 的总和,...} k从i到j-1循环

如果嫌递推麻烦的话可以记忆化搜索,很简单的

Pascal Code

program rqnoj490;

var
n:longint;
a,s:array[0..200+10] of longint;
f:array[0..200+10,0..200+10] of longint;

procedure init;
begin
assign(input,'rqnoj490.in');
assign(output,'rqnoj490.out');
reset(input);
rewrite(output);
end;

procedure outit;
begin
close(input);
close(output);
halt;
end;

procedure readdata;
var
i:longint;
begin
read(n);
for i:=1 to n do
begin
read(a[i]);
a[i+n]:=a[i];
end;
for i:=1 to 2*n do
s[i]:=s[i-1]+a[i];
end;

function sum(i,j:longint):longint;
begin
if i<=j then exit(s[j]-s[i-1])
else exit(s[j+n]-s[i-1]);
end;

function min(i,j:longint):longint;
var
k:longint;
begin
if f[i,j]<>$07070707 then exit(f[i,j]);
if i=j then exit(0);
for k:=i to j-1 do
begin
if f[i,j]>min(i,k)+min(k+1,j)+sum(i,j) then
f[i,j]:=min(i,k)+min(k+1,j)+sum(i,j);
end;
exit(f[i,j]);
end;

function max(i,j:longint):longint;
var
k:longint;
begin
if f[i,j]<>0 then exit(f[i,j]);
if i=j then exit(0);
for k:=i to j-1 do
begin
if f[i,j]<max(i,k)+max(k+1,j)+sum(i,j) then
f[i,j]:=max(i,k)+max(k+1,j)+sum(i,j);
end;
exit(f[i,j]);
end;

procedure main;
var
ans,i,j:longint;
begin
ans:=maxlongint;
fillchar(f,sizeof(f),$7);
for i:=1 to n do
if ans>min(i,i+n-1) then
ans:=min(i,i+n-1);
writeln(ans);
ans:=0;
fillchar(f,sizeof(f),0);
for i:=1 to n do
if ans<max(i,i+n-1) then
ans:=max(i,i+n-1);
writeln(ans);
end;

begin
init;
readdata;
main;
outit;
end.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: