汉诺塔递归算法

来源:互联网 发布:java视频教程马士兵 编辑:程序博客网 时间:2024/06/04 23:36

汉诺塔递归算法

今天在看廖雪峰大大的Python教程时,有一道汉诺塔编程问题,自己想了想,网上看了看资料,觉得挺有意思,就记录一下思路:

汉诺塔的问题:(百度百科引用)

汉诺塔问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

汉诺塔
下面是我的一些分析思路,我会尽量让思路清晰、简洁!

首先把题目限制规则进行简化:

  • 大盘只能放在小盘下面
  • 每次只能拿柱子最上面的盘子

然后给柱子和盘子编号:

  • 盘子最初所在的柱子为A号柱子,目的地是C号柱子,B号柱子空闲
  • 盘子从上到下(从小到大)依次编号为1,2,3,,,,,,n

下面给出分析思路:

为了分析方便,这里 n=64 (一共64个盘子)。在盘子移动的过程中,我们第一个想要完成的目标应该是让最大的盘子(编号64)放到C柱的最下面,而要从A柱拿到最大的盘子,它上面的63个盘子都必须被移走,这63个盘子放在哪里呢????


因为C柱要接收来自A柱的最大盘子,所以这63个盘子只能放在B柱上,而且是整齐的放在B柱,这在实际中是可以完成的。这里先假设我们通过一系列神一样的操作(这些操作目前未知,后面着重分析),使得63个盘子放在了B柱上,然后从A柱拿出64号盘子放在了C柱的最下面。恭喜你!我们完成了第一个盘子


现在,A柱上面没有盘子,B柱整齐的放着63个盘子,C柱上有最大盘子,它上面可以放任何盘子,因为所有的盘子都比它小。这时,你就会发现B柱目前的情形和一开始A柱的情形十分相似,就是少了64号盘子,然后又采用一系列神一样的操作把编号0-62号盘子都移到了A柱上,整齐的放着,然后B柱把63号盘子放在了C柱上(C柱有64,63号盘子了)。这一步完成后B柱空了,A柱上面整齐的放着62个盘子,情形又是如此的相似,然后又是神一样的操作,移走上面的61个盘子………………………..依次类推,盘子最终都会移动到C柱上面。


观察上述过程,我们挑选出这样的一些时刻,就是上述的A柱或者B柱准备把目前最大号的盘子拿出放到C盘上,这样的时刻一共有64个,我们记为times64.63,62…………………1

开始——->times64———>times63………………………———->times2———–>times1

箭头代表一系列神一样的移动操作,下面来分析这个神一样的步骤!!!!!

在开始时刻,64个盘子全部在A柱上,如何将上面的63个盘子移动到B柱上???????这个解决思路就是递归的体现,或者说是数学归纳法


我们假设已经有办法把63个盘子从一根柱子移动到另一根柱子上,这一共需要k次移位。那么把64个柱子移动到另一根柱子(可以是目的地柱子)上也就只需要(k+ k + 1)次移动。如何理解这个公式呢?打个比方,一开始,我们用了k次移动把63个盘子移到了B柱上,然后再把64号盘子移动到C柱上,然后又用K次移动就可以把B柱的63个盘子全部移动到C柱上,这一共只需要(2*k+1)次移动。


现在问题的难点就是如何求解这k次移位,这里我们用递归的思想,63个盘子的移动又可以假设到62个盘子的移动方法已知,依次类推,直到移动3个盘子方法已知,而3个盘子的移动很简单,下列移动就可以实现:

A –> C
A –> B
C –> B
A –> C
B –> A
B –> C
A –> C
反过来,由数学归纳法,初始3个盘子移动方法可知,就可以一步步推出4,5,6,7,,,,,,64个盘子的移动方法。
python代码如下(递归实现):

def move(n, a, b, c):    if n==3:        print(a,"-->",c)        print(a,"-->",b)        print(c,"-->",b)        print(a,"-->",c)        print(b,"-->",a)        print(b,"-->",c)        print(a,"-->",c)        return    move(n-1,a,c,b)  //移动上面的n-1个盘子到空闲的柱子上    print(a,"-->",c,"------------")   //把最大号盘子移动到目的地柱子    move(n-1,b,a,c)   //把先前移动来的n-1个盘子移动到目的地柱子上move(4,'A','B','C')   //测试代码

语句很简单,不得不感叹Python的简介。
测试输出:

A --> BA --> CB --> CA --> BC --> AC --> BA --> BA --> C ------------B --> CB --> AC --> AB --> CA --> BA --> CB --> C

好了,问题到此结束,思路应该没什么问题,至于代码效果,只能检测一下4个盘子,多的盘子我也不会对结果检测了。哪位大牛有方法可以推荐哈!

原创粉丝点击