vijos p1038(添加括号(石子合并))
一道动态规划的题目。
区间动规?我不知道......
第一次接触这种类型的动规,区间动规吧...
就是石子合并。
方程:
F[i,j] = min{F[i,k] + F[k + 1,j] + c[i,j] | i <= k < j}。
我们可以用递推的方法实现它,但是如何递推是个问题。
自然而然地,先求得长度为1的区间,然后是长度为2的区间,然后3.....
至于添括号的方法和各个中间和,我们可以用两个字符串数组来处理他们。
具体看代码:
1 program p1038; uses math; 2 var 3 i,j,k,l,m,n,ans:longint; 4 s:array[0..30]of longint; 5 st:string; 6 c,d,f:array[0..30,0..30]of longint; 7 st1,st2:array[0..30,0..30]of string; 8 {function haha(a,b:longint):longint; 9 var 10 i,j,k:longint; 11 begin 12 if b-a=1 then haha:=a+b 13 else 14 begin 15 haha:=min(haha(a+1,b),haha(a,b-1))+c[a,b]; 16 end 17 end;} 18 begin 19 assign(input,'p1038.in'); 20 reset(input); 21 fillchar(c,sizeof(c),0); 22 fillchar(f,sizeof(f),0); 23 read(n); 24 for i:=1 to n do read(s[i]); 25 for i:=1 to n do 26 for j:=1 to i-1 do 27 for l:=j to i do 28 c[j,i]:=c[j,i]+s[l]; 29 for i:=1 to n do 30 c[i,i]:=s[i]; 31 for i:=1 to n do 32 for j:=1 to n do 33 f[i,j]:=maxlongint; 34 for i:=1 to n do 35 f[i,i]:=0; 36 for i:=1 to n do 37 str(s[i],st2[i,i]);//对中间和预处理 38 for i:=1 to n-1 do 39 for j:=1 to n-i do 40 for k:=j to j+i-1 do 41 begin 42 if f[j,j+i]>=f[j,k]+f[k+1,j+i]+c[j,j+i] then 43 begin 44 str(c[j,j+i],st); 45 st1[j,j+i]:=st1[j,k]+st1[k+1,j+i]+' '+st;//各个中间和 46 st2[j,j+i]:='('+st2[j,k]+'+'+st2[k+1,j+i]+')';//添括号的方法 47 end; 48 f[j,j+i]:=min(f[j,j+i],f[j,k]+f[k+1,j+i]+c[j,j+i]); 49 end; 50 writeln(st2[1,n]); 51 writeln(f[1,n]); 52 delete(st1[1,n],1,1); 53 writeln(st1[1,n]); 54 close(input); 55 end.