问题描述: | 定义于字母表S={a,b,c}上的乘法表如下 | |
编程任务: | 对于给定的字符串x= x1x2...xn,计算有多少种不同的加括号方式,使由x 导出的加括号表达 式的值为a。 | |
数据输入: | 输入数据。第1 行中给出一个字符串。 | |
结果输出: | 将计算结果输出。计算出的加括号方式数。 | |
样例: | bbbba | 6 |
核心思想: | 区间dp,f[l,r,num]=f[l,r,num]+dp(l,i,x1)*dp(i+1,r,x2) l到r间得到的num是从l到i的num*从i+1 到r的num得到的。递归版 |
var
a:array[1..3,1..3]of1..3=((2,2,1),(3,2,1),(1,3,3));
b:array['a'..'c']of 1..3=(1,2,3);
f:array[0..255,0..255,1..3]of longint;
s:string;
function dp(l,r,num:longint):longint;
var
i:longint;
begin
iff[l,r,num]>=0 then exit(f[l,r,num]); {<记忆化>}
f[l,r,num]:=0;
ifl=r then{<返回自己>}
begin
ifnum=b[s[l]] then f[l,r,num]:=1;
exit(f[l,r,num]);
end;
ifr-l=1 then{<返回乘法结果>}
begin
ifnum=a[b[s[l]],b[s[r]]] then f[l,r,num]:=1;
exit(f[l,r,num]);
end;
fori:=l to r do
case num of{<分类讨论>}
1:begin
f[l,r,num]:=f[l,r,num]+dp(l,i,3)*dp(i+1,r,1);
f[l,r,num]:=f[l,r,num]+dp(l,i,1)*dp(i+1,r,3);
f[l,r,num]:=f[l,r,num]+dp(l,i,2)*dp(i+1,r,3);
end;
2:begin
f[l,r,num]:=f[l,r,num]+dp(l,i,1)*dp(i+1,r,1);
f[l,r,num]:=f[l,r,num]+dp(l,i,2)*dp(i+1,r,2);
f[l,r,num]:=f[l,r,num]+dp(l,i,1)*dp(i+1,r,2);
end;
3:begin
f[l,r,num]:=f[l,r,num]+dp(l,i,2)*dp(i+1,r,1);
f[l,r,num]:=f[l,r,num]+dp(l,i,3)*dp(i+1,r,2);
f[l,r,num]:=f[l,r,num]+dp(l,i,3)*dp(i+1,r,3);
end;
end;
exit(f[l,r,num]);
end;
begin
assign(input,'p37.in');reset(input);
assign(output,'p37.out');rewrite(output);
fillchar(f,sizeof(f),255);
readln(s);
writeln(dp(1,length(s),1));
close(input);close(output);
end.
题目来源:《算法设计与分析》第三章动态规划