P1044 [NOIP2003 普及组] 栈——一种容易理解的方式

这篇博客解析了NOIP2003普及组的P1044题,通过动态规划的方法求解序列经过入栈出栈操作后的可能性。博主详细介绍了思路,定义了函数R(eleNum, outNum)表示栈中和外部元素个数,并通过画图解释了动态规划的解题过程,给出了递推公式和简洁的代码实现。" 125006887,10995189,使用gitee流水线实现Java项目自动化部署,"['自动化', '运维', 'Java开发', 'Git', '持续集成']
摘要由CSDN通过智能技术生成

P1044 [NOIP2003 普及组] 栈——一种容易理解的方式


转载请注明出处

简述

这是洛谷里的一道题,也是一道非常经典的题,解法有很多,如卡特兰数、动态规划、记忆化搜索,我自己花了一个下午时间把这道题搞明白,方法是很纯粹的动态规划,稍后在代码中便可看出。我会在后面把个人思路尽我所能地表达清楚,若有更好见解也欢迎你的留言与私信,感谢你的阅读。

题目概述

题目在此简述,洛谷中题目链接在此。简单来讲,我们需要求一个1到n的序列经过一次入栈与出栈后,得到的输出序列有多少种

下面来举一个例子,假如n=3,结果为5,五种结果分别为

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1

个人思路

在我尝试了几种想法之后,我觉得画图能够较为容易把我的思路表达出来,也稍微费了点时间。

首先给出这么一个定义

  • 函数R(eleNum, outNum)表示当栈中元素个数为eleNum、外部元素个数为outNum时,最后输出序列的种数。

拿上面n=3的例子来说,开始时eleNum=0、outNum=3,因为确实此时栈中还没有一个元素,外部元素有3个,所以它可以表示成R(0, 3);然后我们把1入栈(注意:此时我们并未说1是否要出栈,那是后面要考虑的事情,意思是在后面它可以选择在何时或者),此时它可以表示成R(1, 2),意思大致如此。

现在我们来画几棵树

在这里插入图片描述

  • 当n=1时,显然R(0,1)=1,这里要说明的是,因为此时栈中为空,我们可以将一个元素入栈,所以R(0,1)=R(1,0)
  • 当n=2时,我们先将一个元素入栈,然后考虑第二层(左侧为元素出栈,右侧为不出栈
    • 在左侧,栈再次为空,尝试再将一个元素入栈,我们发现它是R(1,0)=1
    • 在右侧,1未出栈,我们接下来将2入栈,结果在此时很容易看出R(2,0)=1
    • 求和R(0,2)=R(1,0)+R(2,0)=2
  • 当n=3时,分析起来依然不难,1入栈后,考虑第二层
    • 在左侧,栈为空,我们将2入栈,此时栈内元素数eleNum为1,外部元素数outNum为1(只有3),结果也就是R(1,1),很幸运的,我们发现R(1,1)我们在n=2时,已经求过,它是2
    • 在右侧,我们将2接着入栈,现在还需要考虑第三层
      • 左侧,当将2出栈后,因为栈不为空,我们不能将新元素入栈(栈内元素1需要考虑在后面何时出栈),所以R(1,1)!=R(2,0),事实上,只有eleNum为0,R(0,n)=R(1,n-1)才成立(你可以仔细想一下,考虑是否如此)。依然是很幸运,我们再次遇到R(1,1)
      • 右侧,当3入栈后,它变成了R(3,0),我们可以不假思索的给出答案R(3,0)=1。现在,你应该能看出一点是R(n,0)=1
  • 当n=4时,我想你应该愿意自己尝试一下(最右侧的树),结果在树的上方已经给出。

公式

如果你了解过动态规划的话,给出公式并不难(如果你明白上面的部分,你应该是可以给出公式的),它们像下面这样

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值