Python求解人字形铁路问题:递归程序设计艺术(5)

如下图,有一段人字形的铁路,火车只能从右边铁路线驶进,并且只能从左边铁路线驶出。驶进来的火车可以停在人字形的上半部分铁路线上,从而让后进来的火车先从左边铁路线驶出。当然它也可以进来之后不作停留直接驶出。假设右边有n列火车,问从左边驶出的n列火车的排列有多少种?

人字形铁路问题:火车只能右边进左边出

比如假设右边有3列火车ABC,则从左边驶出的火车的排列只有5种:ABCACBBACBCACBA。3列火车的所有6种排列里唯有CAB是不可能的。因为C要想第一个出来,则AB必须进入人字形铁路的上半部分不出来,等C进入再出来之后再出来。此时,列车出来的顺序只能是CBA,而不可能是CAB

显然,这一题的输入参数是右边等待进入铁路的火车的数量n。这当然没有错误,可问题是接下来的递归推导比较困难。为了解决这个难题,我们再增加一个参数m,表示待在铁路上半部分的火车的数量,初值是0。

显然,递归边界是n = 0。此时,不论m等于多少,这些火车都只能按照次序一一驶出。所以排列数是1。

递归假设比较好理解,我们这里略过不提。对于递归推导,当两个参数分别是nm时,我们有两种方法分解问题。第一,右边等待的n列火车中的第一列开进铁路,这时问题参数分别转化为n-1、m+1;第二,停在上半部分铁路上的m列火车中的第一列驶出,这时问题参数分别转化为nm-1,当然前提是m>0。这两种方法得到的排列不会重复,并且不可能存在某个排列是这两种方法覆盖不了的。所以我们分别用这两组参数进行递归调用,再把结果相加即可。代码如下:

解决人字形铁路问题的递归程序

def get_trains(n, m=0):
    if n == 0:
        return 1
    result = get_trains(n-1, m+1)
    if m > 0:
        result += get_trains(n, m-1)
    return result

if __name__ == '__main__':
    for n in range(1, 10+1):
        print(n, get_trains(n))

运行结果如下:

1 1
2 2
3 5
4 14
5 42
6 132
7 429
8 1430
9 4862
10 16796

这个问题有意思的地方在于,虽然m的值加1了,但是子问题的参数还是比原问题更靠近递归边界,这是因为递归边界仅跟参数n有关,跟m无关。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方林博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值