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.

浙公网安备 33010602011771号