关于括号式子的计数

  • CSDN
  • CSDN社区
  • 专题开发/技术/项目
  • 数据结构与算法
  • 超超版主的问题:

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

    能否找到递推公式? 

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

    tailzhou  网友的解答:

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

    对由i(i >=k and i <=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 >

    #define MAX_N 20

    int dp[MAX_N+1][MAX_N+1];

    void fun(int n,int k)
    {
    int i,j;
    for (i=k;i <n;++i)
    {
    int tmp=0;

    for (j=0;j <=n-i;++j)
    {
      int tmp_i=j;
    int tmp_j=n-i-j;
    int tmp_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];
    }

    int main(int argc, char* argv[])
    {

    //最深嵌套层次为k,那么肯定存在一个层次为k-1的式子,其外围再有一对括号;
    //这对括号外再没有嵌套的括号;
    int n,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:%3d k:%3d dp:%10d/n",n,k,dp[n][k]);
    }
    }

    fun(20,2);

    printf("input n{max:%d} and k{max:%d}:",MAX_N,MAX_N);
    while (scanf("%d %d",&n,&k)==2)
    {
    printf("%d %d : %d /n" ,n,k,dp[n][k]);
    printf("input n{max:%d} and k{max:%d}:",MAX_N,MAX_N);
    }

    return 0;
    }

    顺手将其改写成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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值