汉诺塔问题函数

汉诺塔问题

汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候作了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序从新摆放在另外一根柱子上。而且规定,任什么时候候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操做?html


分析

一股脑地考虑每一步如何移动很困难,咱们能够换个思路。三根柱子依次为a、b、c柱,如今目的是将a柱圆盘移动到c柱。python

先假设除最下面的盘子以外,咱们已经成功地将上面的63个盘子移到了b柱,此时只要将最下面的盘子由a移动到c便可。ide

当最大的盘子由a移到c后,b上是余下的63个盘子,a为空。所以如今的目标就变成了将这63个盘子由b移到c。这个问题和原来的问题彻底同样,只是由a柱换为了b柱,规模由64变为了63。所以能够采用相同的方法,先将上面的62个盘子由b移到a,再将最下面的盘子移到c……对照下面的过程,试着是否能找到规律:函数

1. 将b柱子做为辅助,把a上的63个圆盘移动到b上
2. 将a上最后一个圆盘移动到c
3. 将a做为辅助,把b上的62个圆盘移动到a上
4. 将b上的最后一个圆盘移动到c
5. ......

也许你已经发现规律了,即每次都是先将其余圆盘移动到辅助柱子上,并将最底下的圆盘移到c柱子上,而后再把原先的柱子做为辅助柱子,并重复此过程。htm

这个过程称为递归,即定义一组基本操做,这组操做将规模小一点(或大一点)的操做当作一个总体——无需关心它的细节,只当它已经完成了——而后执行剩下的操做。而在更小或更大的规模中也依此操做,直到规模达到预约值。blog


Python函数

在python中,咱们能够用递归函数来计算汉诺塔问题的解决方案。递归

def move(n,a,b,c):
    if n == 1:
        print a, '-->', c    else:
        move(n-1, a, c, b)
        move(1, a, b, c)
        move(n-1, b, a, c)

>>> move(3,'A','B','C')A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C>>> move(4,'A','B','C')A --> B
A --> C
B --> C
A --> B
C --> A
C --> B
A --> B
A --> C
B --> C
B --> A
C --> A
B --> C
A --> B
A --> C
B --> C

以 n=3 为例,咱们来看看执行过程:图片

在这里插入图片描述

如今咱们想一想,这个函数为何这么写?反推一下:it

1. 当 n = 1 ,即 move(1,a,b,c) 时,移动过程是 A --> C ,因此函数能够是

   move(1, a, b, c)

2. 当 n = 2 ,即 move(2,a,b,c) 时,移动过程是 
   
   A --> B
   A --> C
   B --> C ,
   
   因此函数能够是

   move(1, a, c, b)         =       move(2-1, a, c, b)
   
   move(1, a, b, c)         =       move(1, a, b, c)
   
   move(1, b, a, c)         =       move(2-1, b, a, c)
   
3. 当 n = 3 ,即 move(3,a,b,c) 时,移动过程是
   
   A --> C
   A --> B
   C --> B
   A --> C
   B --> A
   B --> C
   A --> C ,
   
   因此函数能够是
   
   move(1, a, b, c)
   move(1, a, c, b)         =       move(3-1, a, c, b)
   move(1, c, a, b)
   
   move(1, a, b, c)         =       move(1, a, b, c)
   
   move(1, b, c, a)
   move(1, b, a, c)         =       move(3-1, b, a, c)
   move(1, a, b, c)

4. 当 n = 4 ,即 move(3,a,b,c) 时,移动过程是
   
   A --> B
   A --> C
   B --> C
   A --> B
   C --> A
   C --> B
   A --> B
   A --> C
   B --> C
   B --> A
   C --> A
   B --> C
   A --> B
   A --> C
   B --> C ,
   
   因此函数能够是
   
   move(1, a, c, b)
   move(1, a, b, c)
   move(1, b, a, c)
   move(1, a, c, b)         =       move(4-1, a, c, b)
   move(1, c, b, a)
   move(1, c, a, b)
   move(1, a, c, b)
   
   move(1, a, b, c)         =       move(1, a, b, c)
   
   move(1, b, a, c)
   move(1, b, c, a)
   move(1, c, b, a)
   move(1, b, a, c)         =       move(4-1, b, a, c)
   move(1, a, c, b)
   move(1, a, b, c)
   move(1, b, a, c)

5. 依次类推,当为n时,须要 2^n-1 步才能完成整个移动过程,而函数能够是

   move(n-1, a, c, b)
   move(1, a, b, c)
   move(n-1, b, a, c)

汉诺塔问题颇有意思,经过递归函数能够简单清晰的将其表示出来,递归实际上就是用本身来定义本身。class

相关文章
相关标签/搜索