当前位置: 首页 > news >正文

2003NOIP普及组真题 3. 栈

线上OJ 地址:

【03NOIP普及组】栈

核心思想

1、这类题目和火车进站出站是同一类问题,常规解法有两种。一、动态规划;二、卡特兰公式

解法一:动态规划

1、设 f[i][j]: i表示进栈的个数,j表示“进栈的i个”中出栈的个数。所以 j≤i

举例:
f[1][0]=1:进栈1个元素,出栈0个元素。此时只有1种可能,就是进栈的唯一元素不动。
f[1][1]=1:进栈1个元素,出栈1个元素。此时只有1种可能,就是把进栈的唯一元素直接出栈。
f[2][0]=1:进栈2个元素,出栈0个元素。此时只有1种可能,就是进栈的两个元素都不动。
f[2][1]:进栈2个元素,出栈1个元素。此时有2种可能,第一种是在f[1][1]的情况下第2个元素进栈;第二种可能是在f[2][0]的情况下出栈一个元素

2、根据以上推导,可以得到动态转移方程: f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i ] [ j − 1 ] ( j ≤ i ) f[i][j] = f[i-1][j] + f[i][j-1] ( j≤i) f[i][j]=f[i1][j]+f[i][j1]ji
“进栈 i 个,出栈 j 个”两种 状态转移而来:

① 进栈 i-1 个,出栈 j 个(此时再进栈1个就好);
② 进栈 i 个,出栈 j-1 个(此时再出栈1个就好)

3、初始化:不管进栈几个,出栈为0的,都只有1种可能性,就是都不出
4、注意 j≤i
5、最后要输出的结果就是 f[n][n],表示进栈n个,出栈n个的可能性
6、注:动态规划的好处是可以求出任意进栈出栈 f[i][j] 的数量。

题解代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;const int N = 20;ll f[N][N];
// f[i][j]:  i表示进栈的个数,j表示“进栈的i个”中出栈的个数。所以j<=i
// f[i][j] = f[i-1][j] + f[i][j-1]
int main()
{int n;scanf("%d", &n);for(int i = 0; i <= n; i++)  f[i][0] = 1;for(int i = 1; i <= n; i++)for(int j = 1; j <= i; j++)f[i][j] = f[i-1][j] + f[i][j-1];printf("%d", f[n][n]);return 0;
}
解法二:卡特兰数

1、本题可以用卡特兰数来解

背景:

卡特兰数(Catalan numbers)是一系列组合数学中出现的自然数,广泛应用于各种计数问题,如二叉树、括号匹配、凸多边形的三角剖分、火车进站出站、有序的01序列等。

卡特兰数的递推公式如下:
C n = ∑ i = 0 n − 1 C i ⋅ C n − 1 − i C_n = \sum_{i=0}^{n-1} C_i \cdot C_{n-1-i} Cn=i=0n1CiCn1i

其中 C 0 = 1 C_0=1 C0=1。这一公式表明第n 个卡特兰数等于前 n 个卡特兰数的乘积和。
C 0 = 1 C_0=1 C0=1
C 1 = C 0 ⋅ C 0 = 1 C_1=C_0⋅C_0=1 C1=C0C0=1
C 2 = C 0 ⋅ C 1 + C 1 ⋅ C 0 = 1 + 1 = 2 C_2=C_0⋅C_1+C_1⋅C_0=1+1=2 C2=C0C1+C1C0=1+1=2
C 3 = C 0 ⋅ C 2 + C 1 ⋅ C 1 + C 2 ⋅ C 0 = 2 + 1 + 2 = 5 C_3=C_0⋅C_2+C_1⋅C_1+C_2⋅C_0=2+1+2=5 C3=C0C2+C1C1+C2C0=2+1+2=5
C 4 = C 0 ⋅ C 3 + C 1 ⋅ C 2 + C 2 ⋅ C 1 + C 3 ⋅ C 0 = 5 + 2 + 2 + 5 = 14 C_4=C_0⋅C_3+C_1⋅C_2+C_2⋅C_1+C_3⋅C_0=5+2+2+5=14 C4=C0C3+C1C2+C2C1+C3C0=5+2+2+5=14

卡特兰数还可以用以下闭式公式表示:
C n = 1 n + 1 ( 2 n n ) C_n = \frac{1}{n+1} \binom{2n}{n} Cn=n+11(n2n) 公式 ①

2、本题因为输入是n,所以是求解第 n 个卡特兰数,故可以直接 公式① 即可。
3、求解公式①时,为了计算 ( 2 n n ) \binom{2n}{n} (n2n),可以采用组合的递推公式:

( n m ) = ( n − 1 m ) + ( n − 1 m − 1 ) \binom{n}{m}=\binom{n-1}{m}+\binom{n-1}{m-1} (mn)=(mn1)+(m1n1) 公式 ②

公式②的意思是,从 n 个元素中选取 m 个元素的方式,可以通过以下两种方式得到:
1、不选择第 n 个元素:则需要从前 n−1 个元素中选 m 个,这种方式有 ( n − 1 m ) \binom{n-1}{m} (mn1) 种。
2、选择第 n 个元素:则需要从前 n−1 个元素中选m−1 个,这种方式有 ( n − 1 m − 1 ) \binom{n-1}{m-1} (m1n1)种。
因此,总的选择方式为这两种方式的和。

#include <bits/stdc++.h>
#define ll long long
using namespace std;const int N = 20;ll c[2*N][N];  // c[i][j]:在i个里面挑j个
// c[i][j] = c[i-1][j] + c[i-1][j-1]
int main()
{int n;scanf("%d", &n);for(int i = 0; i <= 2*n; i++)  c[i][0] = 1;for(int i = 1; i <= 2*n; i++)for(int j = 1; j <= i; j++)c[i][j] = c[i-1][j] + c[i-1][j-1];printf("%d\n", c[2*n][n]/(n+1) );return 0;
}

备注:
卡特兰数的应用:
1、括号匹配问题:n对括号中,有多少种合法的匹配方式(由于合法的任意前缀是:左括号的数量不可能小于右括号的数量。故,若记左括号为0,右括号为1,则合法的任意前缀变为:0的数量不可能小于1的数量)
2、出栈次序问题:一个栈的进栈序列为1,2,3…n,有多少种不同的出栈序列(合法的任意前缀是:入栈的数量不可能小于出栈的数量。故,若记入栈为0,出栈为1,则合法的任意前缀变为:0的数量不可能小于1的数量)
3、有序列表问题:给定长度为n的仅包含01的字符串,任意前缀中0的数量不小于1的数量的组合方式有多少种
4、二叉树的计数: 卡特兰数 Cn 表示有 n 个节点的不同二叉树的个数
5、凸多边形的三角剖分:卡特兰数 Cn 表示一个 n+2 边凸多边形可以分成 n 个三角形的不同方式的数量
6、根插入排列:卡特兰数Cn 表示将 n 个元素插入到有根树中的不同方式数量。
7、独特路径问题:卡特兰数 Cn 表示在一个 2n 阶的棋盘上,从左下角到右上角且不穿越对角线的路径数。

解法三、打表法

1、由于本题的 n 不大。故可先用卡特兰数计算每一个n对应的可能性(此时无所谓是否超时)
2、将每一个n对应的结果直接做到数组里。

#include<bits/stdc++.h>
using namespace std;
int main()
{int n, ans[20] = {1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012,742900, 2674440, 9694845, 35357670, 129644790, 477638700};scanf("%d", &n);printf("%d", ans[n]);return 0;
}

相关文章:

  • “Apache Kylin 实战指南:从安装到高级优化的全面教程
  • 环 境 变 量
  • 夕小瑶:资本寒冬下的AI创业一年
  • vue3 监听器,组合式API的watch用法
  • 软考 系统架构设计师系列知识点之杂项集萃(28)
  • 3588麒麟系统硬解码实战
  • gcc: coverage: gcda文件没有生成另一例:so文件调用__gcov_dump
  • 【Python】解决Python报错:TypeError: ‘int‘ object is not callable
  • opencv实战小结-银行卡号识别
  • 如何利用Varjo混合现实技术改变飞机维修训练方式
  • 关于RDMA传输的基本流量控制
  • Linux 中常用的设置、工具和操作
  • LeetCode题练习与总结:三角形最小路径和--120
  • 有待挖掘的金矿:大模型的幻觉之境
  • LeetCode ---400周赛
  • #Java异常处理
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • ComponentOne 2017 V2版本正式发布
  • HTTP 简介
  • Lsb图片隐写
  • MD5加密原理解析及OC版原理实现
  • tab.js分享及浏览器兼容性问题汇总
  • WebSocket使用
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 将 Measurements 和 Units 应用到物理学
  • 解析带emoji和链接的聊天系统消息
  • 驱动程序原理
  • 推荐一个React的管理后台框架
  • 王永庆:技术创新改变教育未来
  • 问题之ssh中Host key verification failed的解决
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 函数计算新功能-----支持C#函数
  • !$boo在php中什么意思,php前戏
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #162 (Div. 2)
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (MATLAB)第五章-矩阵运算
  • (SERIES10)DM逻辑备份还原
  • (undone) MIT6.824 Lecture1 笔记
  • (二)springcloud实战之config配置中心
  • (二)换源+apt-get基础配置+搜狗拼音
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (十八)Flink CEP 详解
  • (十六)、把镜像推送到私有化 Docker 仓库
  • (算法)Travel Information Center
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)Google的Objective-C编码规范
  • (转)linux下的时间函数使用
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)真正的中国天气api接口xml,json(求加精) ...