历届试题_出栈次序
X星球特别讲究秩序,所有道路都是单行线。一个甲壳虫车队,共16辆车,按照编号先后发车,夹在其它车流中,缓缓前行。
路边有个死胡同,只能容一辆车通过,是临时的检查站,如图【p1.png】所示。
X星球太死板,要求每辆路过的车必须进入检查站,也可能不检查就放行,也可能仔细检查。
如果车辆进入检查站和离开的次序可以任意交错。那么,该车队再次上路后,可能的次序有多少种?
为了方便起见,假设检查站可容纳任意数量的汽车。
显然,如果车队只有1辆车,可能次序1种;2辆车可能次序2种;3辆车可能次序5种。 现在足足有16辆车啊,亲!需要你计算出可能次序的数目。
思路:这道题其实是一个进栈出栈的题,也就是问所有出栈顺序的可能数,如果之前了解过这方面的问题的同学,这道题其实就是送分题,可以直接利用卡特兰数的公式求解,不了解的话
可以看一下我之前写的一篇博客,也是关于进出栈次序的问题,有对卡特兰数详细的分析https://www.cnblogs.com/henuliulei/p/9867106.html,下面是几种网上的常见求解思路,做了一下总结
方法一:求出栈次序,无非就是问一共有多少种满足要求的排列,满足条件在本题中就是指,只有站中有“车”,才能够出来。假设1,代表进站,0代表出站,r代表进栈的个数,L代表出栈的个数,易知
只有进栈的个数r大于等于出栈的个数L才可以出栈或进栈,否则只能进栈,因此可以进行回溯求出所有可能的方案。
1 #include<iostream> 2 3 using namespace std; 4 5 int num=0; 6 7 8 9 void dfs(int n,int r,int l){ 10 11 if(n==32){ 12 13 num++; 14 15 return; 16 17 } 18 19 20 21 if(r>l){ 22 23 if(r<16) 24 25 dfs(n+1,r+1,l); 26 27 if(l<16) 28 29 dfs(n+1,r,l+1); 30 31 }else{ 32 33 if(r==l) 34 35 if(r<16) 36 37 dfs(n+1,r+1,l); 38 39 } 40 41 42 43 return; 44 45 } 46 47 48 49 int main(){ 50 51 52 53 dfs(0,0,0); 54 55 cout<<num<<endl; 56 57 return 0; 58 59 }
方法二:利用卡特兰数的公式f(n) = f(0)*f(n-1) + f(1)*f(n-2) + ... +f(n-1)*f(0)
1 #include <stdio.h> 2 3 int main() 4 5 { 6 7 int f[20]; 8 9 int i,j; 10 11 f[0]=1; 12 13 f[1]=1; 14 15 f[2]=2; 16 17 f[3]=5; 18 19 for(i=4;i<=16;i++) 20 21 f[i]=0;//注意必须给其他数组置0 22 23 for(i=4; i<=16; i++) //求16个元素 24 25 { 26 27 for(j=0; j<=i-1; j++) 28 29 f[i]+=f[j]*f[i-1-j]; 30 31 } 32 33 printf("%d",f[16]); 34 35 return 0; 36 37 }
方法三:卡特兰数的另一种递推公式h(n)=h(n-1)*(4*n-2)/(n+1)
1 #include <stdio.h> 2 3 int main() 4 5 { 6 7 int n,h[20]; 8 9 h[0]=1; 10 11 h[1]=1; 12 13 for(n=2;n<=16;n++) 14 15 h[n]=h[n-1]*(4*n-2)/(n+1); 16 17 printf("%d\n",h[16]); 18 19 return 0; 20 21 }
方法四:卡特兰数递推公式的解:h(n)=C(n,2n)*(2n-1) (n=0,1,2,...)
该种方法有一定的局限性,因为n>14时数据会超出unsigned long long int 的范围(0~2^64-1),不过可以考虑先求n=14的解,再用计算器推出n=16的解。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 int m; 5 unsigned long long int f(int n) 6 { 7 unsigned long long int m1=1; 8 unsigned long long int m2=1; 9 for(int i=1;i<=n;i++){ 10 m1*=i; 11 } 12 for(int i=2*n;i>n;i--){ 13 m2*=i; 14 } 15 // cout << m2 << "--" << m1 << endl; 16 m=m2/m1; 17 return m; 18 } 19 int main() 20 { 21 22 int n; 23 // while(true){ 24 cin >> n; 25 cout << f(n)/(n+1); 26 // } 27 return 0; 28 }
总之熟记卡特兰数即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!