关于括号式子的计数

括号序列的计数问题
优快云 优快云社区 专题开发/技术/项目 数据结构与算法

超超版主的问题:

如果有n对括号,组成一个式子,而且括号的最深嵌套层次为k
满足这个条件的式子一共有几种?
如果n=3,k=2则有3种:
(())()
()(())
(()())

能否找到递推公式?

------------------------------------------------------------------------------------------

tailzhou 网友的解答:

对于特定的n,k;
深度为k的子式子最少有k个括号,最多有n个括号

对由i(i >=kandi <=n)个括号组成的深度为k的式子可以由dp数组得到;
其他的n-i个括号分布在深度为k的子式子的前后;

为了不重复统计,规定上面深度为k的子式子是大式子中的第一个深度为k的子式子;

分别对前面有j(j >=0,j <=n-i,并且这k个括号组成的式子的最大深度不能大于k-1,也就是最大深度从1到k-1的总数的和)个括号,后面有n-i-j(并且这n-i-j个括号组成的式子的最大深度不能大于k)个括号的情况统计;


#include <stdio.h >

#defineMAX_N20

intdp[MAX_N+1][MAX_N+1];

voidfun(intn,intk)
{
inti,j;
for(i=k;i <n;++i)
{
inttmp=0;

for(j=0;j <=n-i;++j)
{
inttmp_i=j;
inttmp_j=n-i-j;
inttmp_k1=0,tmp_k2=0;
if(tmp_i >k-1)tmp_i=k-1;
if(tmp_j >k)tmp_j=k;

for(;tmp_i >0;tmp_i--)
{
tmp_k1+=dp[j][tmp_i];
}
for(;tmp_j >0;tmp_j--)
{
tmp_k2+=dp[n-i-j][tmp_j];
}

if(tmp_k1 <1)tmp_k1=1;
if(tmp_k2 <1)tmp_k2=1;

tmp+=tmp_k1*tmp_k2;

}
dp[n][k]+=dp[i-1][k-1]*tmp;
}
dp[n][k]+=dp[n-1][k-1];
}

intmain(intargc,char*argv[])
{

//最深嵌套层次为k,那么肯定存在一个层次为k-1的式子,其外围再有一对括号;
//这对括号外再没有嵌套的括号;
intn,k;

for(n=1;n <=MAX_N;n++)
{
dp[n][1]=1;
dp[n][n]=1;
}

for(n=1;n <=MAX_N;n++)
{
for(k=1;k <=n;k++)
{
if(k!=n&&k!=1)fun(n,k);

printf("n:%3dk:%3ddp:%10d\n",n,k,dp[n][k]);
}
}

fun(20,2);

printf("inputn{max:%d}andk{max:%d}:",MAX_N,MAX_N);
while(scanf("%d%d",&n,&k)==2)
{
printf("%d%d:%d\n",n,k,dp[n][k]);
printf("inputn{max:%d}andk{max:%d}:",MAX_N,MAX_N);
}

return0;
}

顺手将其改写成VB代码,如下所示:

Sub fun(ByVal n As Long, ByVal k As Long, ByRef dp())
Dim i As Long, j As Long, temp As Long, temp_i As Long, temp_j As Long, temp_k1 As Long, temp_k2 As Long
For i = k To n - 1
temp = 0
For j = 0 To n - i
temp_i = j
temp_j = n - i - j
temp_k1 = 0
temp_k2 = 0
If temp_i > k - 1 Then temp_i = k - 1
If temp_j > k Then temp_j = k
While temp_i > 0
temp_k1 = temp_k1 + dp(j, temp_i)
temp_i = temp_i - 1
Wend
While temp_j > 0
temp_k2 = temp_k2 + dp(n - i - j, temp_j)
temp_j = temp_j - 1
Wend
If temp_k1 < 1 Then temp_k1 = 1
If temp_k2 < 1 Then temp_k2 = 1
temp = temp + temp_k1 * temp_k2
Next
dp(n, k) = dp(n, k) + dp(i - 1, k - 1) * temp
Next
dp(n, k) = dp(n, k) + dp(n - 1, k - 1)
End Sub


Sub main()
Dim n As Long, k As Long, max_n As Long
max_n = 23
ReDim dp(1 To max_n, 1 To max_n)
For n = 1 To max_n
dp(n, 1) = 1
dp(n, n) = 1
Next
For n = 1 To max_n
For k = 1 To n
If k > 1 And k < n Then fun n, k, dp
Next
Next
[a1].Resize(max_n, max_n) = dp
[a1].Resize(max_n, max_n).Columns.AutoFit
End Sub

在EXCEL中返回:

1                      
11                     
131                    
1751                   
1151871                  
131573391                 
16316913252111                
112748248424775131               
1255134116841053410102151              
15113669566141991975629133171             
110239922185791601787783366912168191            
12047266095991759224369381642253581267207211           
1409570929190696214058149501751402840580991702250231          
1819118822660074476048758795132818514004946305117532225297251         
116383497845187725626658842262375138434565458824441272036165002844348271        
1327671313501582818592462768558854568530629379321215448404984107880225363567403291       
1655353459042179987833179372431945379228638611277658957738122133296643280156519300734402462311      
1131071909639355342617108548332117939506904201105419039026457508106836843576375986391221067393395357525331     
126214323895673169552428368400045431530926352754930225253075117789057514012511882282557702241467864305102505786440592351    
152428762721698517884748124402731715671599011360882980921000186512231849239414383948171253183113790110542128646412698640507659663371   
11048575164531565157781206041828547285655480303520139107737147108242184870646108587770346087977016749045351981891136810443018092548457800319022738391  
12097151431397285479668216514012220027202993521071972454887714812754293917025056548175050852175127695847842567285135279823620712026568541950377175419881310537817411 
14194303113070886614555626635467891298177252283228274300429926585008578803797005432020980377935100156030014155948108150047519647012510612708847829373300572893292570412070412212900431
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值