关于括号式子的计数

优快云 优快云社区 专题开发/技术/项目 数据结构与算法

超超版主的问题:

如果有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             
110239922
<think>好的,我现在需要帮助用户了解计数型动态规划的概念,并提供相关的教程和示例。首先,我得先回忆一下计数型动态规划的基本定义和特点。根据用户提供的引用,特别是引用[1]和引用[4],动态规划通常用于解决具有重叠子问题和最优子结构的问题,而计数型动态规划则是用来计算满足特定条件的方案数目,而不是求最优解。 接下来,我需要确定用户的需求层次。他们可能刚接触动态规划,需要从基础概念入手,然后通过示例来理解应用。因此,回答的结构应该先介绍概念,再讲解步骤,最后给出具体例子,比如引用[4]中提到的背包问题,但需要调整为计数类型的问题。 然后,我需要确保示例的正确性。比如,爬楼梯问题是一个经典的计数型动态规划例子,可以用来展示如何计算到达第n阶楼梯的方法数。另一个例子可能是路径计数问题,这在网格中从起点到终点的路径数目计算,也是常见的计数问题。需要详细说明状态定义、转移方程和初始条件。 另外,用户提到要生成相关问题,我需要根据内容提出几个相关问题,比如与其他类型动态规划的区别、优化方法、应用场景等。这些问题应该能够帮助用户进一步深入学习。 同时,要注意引用格式,用户要求引用的标识自然添加在段落末尾。例如,在解释动态规划定义时引用[^1],在讨论背包问题时引用[^4]。但需要检查提供的引用内容是否与计数型动态规划直接相关,可能需要调整引用标记的位置,确保准确性。 最后,要确保使用正确的中文表达,避免术语错误,并按照用户的要求使用LaTeX格式行内公式和独立公式。例如,状态转移方程需要用$$...$$格式单独成段,变量用$...$格式。 总结步骤: 1. 定义计数型动态规划,引用相关文献。 2. 说明适用场景和核心要素。 3. 分步骤讲解解决步骤。 4. 提供两个示例,详细分析。 5. 生成相关问题,帮助用户拓展思考。 6. 确保引用正确,格式符合要求。</think>### 计数型动态规划详解 #### 一、基本概念 **计数型动态规划**是动态规划的一个分支,其核心目标是计算满足特定约束条件的方案数量,而非寻找最优解[^1]。这类问题通常具有以下特征: - **重叠子问题**:不同路径/决策会重复计算相同状态 - **无后效性**:当前状态仅与历史状态有关,与未来无关 - **计数目标**:最终结果为满足条件的路径/方案总数 #### 二、算法核心要素 1. **状态定义**:用$dp[i]$表示第$i$个状态对应的方案数 2. **状态转移方程**:建立$dp[i]$与子状态的关系式 3. **边界条件**:确定最小子问题的初始值 4. **遍历顺序**:保证计算当前状态时所需子状态已计算完成 #### 三、解决步骤 1. 分析问题是否满足动态规划特征 2. 定义状态表示和状态维度 3. 推导状态转移关系(重点关注方案数的叠加方式) 4. 初始化基础状态 5. 按正确顺序进行状态转移 6. 返回目标状态的计数结果 #### 四、经典示例 ##### 示例1:爬楼梯问题 **问题描述**:每次可爬1或2阶台阶,求到达第$n$阶的不同方法数 **状态定义**: $$dp[i] = \text{到达第i阶的方法总数}$$ **状态转移**: $$dp[i] = dp[i-1] + dp[i-2]$$ **边界条件**: $$dp[0] = 1,\ dp[1] = 1$$ ```python def climb_stairs(n): if n <= 1: return 1 dp = [0]*(n+1) dp[0], dp[1] = 1, 1 for i in range(2, n+1): dp[i] = dp[i-1] + dp[i-2] return dp[n] ``` ##### 示例2:网格路径计数 **问题描述**:在$m \times n$网格中,从左上角到右下角的唯一路径数(只能向右/向下移动) **状态定义**: $$dp[i][j] = \text{到达坐标(i,j)的路径数}$$ **状态转移**: $$dp[i][j] = dp[i-1][j] + dp[i][j-1]$$ **边界条件**: $$dp[0][j] = 1\ (0 \le j < n),\ dp[i][0] = 1\ (0 \le i < m)$$ ```python def unique_paths(m, n): dp = [[1]*n for _ in range(m)] for i in range(1, m): for j in range(1, n): dp[i][j] = dp[i-1][j] + dp[i][j-1] return dp[-1][-1] ``` #### 五、进阶应用场景 1. 组合数计算(如$C(n,k)$) 2. 括号生成方案计数 3. 背包问题变种(如恰好装满背包的方案数) 4. 图论中的路径计数(特殊限制条件下的路径枚举) §§ 相关问题 §§ 1. 如何区分计数型动态规划与最优化动态规划? 2. 计数型动态规划如何避免重复计算? 3. 哪些数学原理支撑着状态转移方程的建立? 4. 如何将组合数学问题转化为动态规划模型? 5. 计数型动态规划在路径问题中有哪些典型应用?[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值