题目: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.
posted on 2012-03-15 10:43  淡·雅·墨  阅读(366)  评论(0)    收藏  举报