算法:DP
分析:NOIP2003普及组题目。
虽然是一道普及组的题目,但仍然是一道挺好的区间DP题目.
处理有环的问题,通常将环拉长,这里采用扩展成两个完全相同的序列并把它们接在一起来表示,设fmin[i,j,k]表示从i到j分成k组之后的最小值,同理得fmax[],先初始化算出从i到j的值是多少,然后进行DP即可。
初始化的时候一定要注意不要太大否则会爆了。
program Vijos1218;
const
maxn=100;
maxm=9;
var
minn,maxx,n,m:longint;
a:array [0..maxn] of longint;
fmin,fmax:array [0..maxn,0..maxn,0..maxm] of longint;
s:array [0..maxn,0..maxn] of longint;
procedure init;
var
i,j,k,p:longint;
begin
readln(n,m);
for i:=1 to n do
begin
readln(a[i]);
a[n+i]:=a[i];
end;
n:=n shl 1;
{初始化过程。}
for i:=1 to n do
begin
for j:=1 to n do
begin
for k:=1 to m do
begin
fmin[i,j,k]:=950112;
fmax[i,j,k]:=-950112;
end;
end;
end;
for i:=1 to n do
begin
for j:=1 to n do
begin
p:=0;
for k:=i to j do inc(p,a[k]);
p:=p mod 10;
if p<0 then inc(p,10);
s[i,j]:=p;
end;
end;
for i:=1 to n do
begin
for j:=i to n do
begin
fmin[i,j,1]:=s[i,j];
fmax[i,j,1]:=s[i,j];
end;
end;
end;
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;
procedure main;
var
i,j,k,l:longint;
begin
for i:=1 to n do
begin
for j:=i to n do
begin
for k:=2 to m do
begin
for l:=i to j-1 do
begin
fmin[i,j,k]:=min(fmin[i,j,k],fmin[i,l,k-1]*s[l+1,j]);
fmax[i,j,k]:=max(fmax[i,j,k],fmax[i,l,k-1]*s[l+1,j]);
end;
end;
end;
end;
end;
procedure outit;
var
i:longint;
begin
minn:=maxlongint;
maxx:=-maxlongint;
n:=n shr 1;
for i:=1 to n do
begin
minn:=min(minn,fmin[i,i+n-1,m]);
maxx:=max(maxx,fmax[i,i+n-1,m]);
end;
end;
begin
assign(input,'VJ1218.in'); reset(input);
assign(output,'VJ1218.out'); rewrite(output);
init;
main;
outit;
writeln(minn);
writeln(maxx);
close(input); close(output);
end.
本文探讨使用区间DP解决有环问题的策略,通过将环拉长并扩展为两个完全相同的序列来表示,实现对复杂情况的有效处理。文章详细解释了如何通过动态规划算法计算最优解,并提供了初始化技巧以避免溢出。
4011

被折叠的 条评论
为什么被折叠?



