题目:http://61.187.179.132/JudgeOnline/problem.php?id=1090
本题首先要要看出是典型的区间动态规划,对于一个区间的最优值,是满足无后效性的(可以类比一下合并石子),那么就开始写方程了,用f[i,j]表示从i到j的最短长度。所以有f[i,j]:=min{f[i,k]+f[k+1,j],f[i,k]+2+数字长度}其含义为,ij区间的最小值,为两个拆开的长度之和或者是自身的折叠。
在判断折叠的时候,用倍数作为前提来卡区间,就可以很好地判断
code:
program third;
var
f : array[0..200,0..200] of integer;
s : string;
i,j,k,len,l,n : longint;
procedure init;
begin
fillchar(f,sizeof(f),1);
readln(s);
n:=length(s);
end; { init }
function have(x,y : longint):boolean;//判断能否折叠
var
i,j,len : Longint;
begin
len:=y-x+1;
for i:=2 to l div len do
for j:=x+(i-1)*len to x+i*Len-1 do
if s[j]<>s[j-(i-1)*len] then
exit(false);
exit(true);
end; { have }
function deal(x:longint):longint;//求数字长度
begin
deal:=0;
while x div 10>0 do
begin
inc(deal);
x:=x div 10;
end;
inc(deal);
end;
procedure work;
begin
for I:=n downto 1 do
for j:=i to n do
begin
l:=j-i+1;
if i=j then
begin
f[i,j]:=1;
continue;
end;
for k:=i to j-1 do
if f[i,k]+f[k+1,j]<f[i,j] then
f[i,j]:=f[i,k]+f[k+1,j];
for k:=i to j-1 do
if (l mod (k-i+1)=0) and (have(i,k)) then
begin
len:=l div (k-i+1);
if f[i,k]+2+deal(len)<f[i,j] then
f[i,j]:=f[i,k]+2+deal(len);
end;
end;
end; { work }
begin
assign(input,'zd.in'); reset(input);
//assign(output,'zd.out'); rewrite(output);
init;
work;
writeln(f[1,n]);
close(input);
close(output);
end.
浙公网安备 33010602011771号