印度有这样一个神话传说:大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆在另一根柱子上。在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动 一个圆盘。 64根柱子移动完毕之日,就是世界毁灭之时。
简略图如下所示:
问题详细分析
此时我们将盘子的个数设为n:
当n=2时:
步骤1:把小圆盘从A移动到B
步骤2:把大圆盘从A移动到C
步骤3:把小圆盘从B移动到C
当n=3时,我们依然可以快速得出它的7个步骤:
1.把第1个盘子从A移到C
2.把第2个盘子从A移到B
3.把第1个盘子从C移到B
4.把第3个盘子从A移到C
5.把第1个盘子从B移到A
6.把第2个盘子从B移到C
7.把第1个盘子从A移到C
当此时共有n个盘子时,则这就是一个递归的过程:
我们将上面的棕黄色的盘子看为一个整体,记为n-1个盘子;将底下的灰咖色盘子记为1个盘子
当n个盘子时:
步骤1:把n-1个圆盘(棕黄色)从A经过C移动到B
步骤2:把第n个圆盘(灰咖色)从A移动到C
步骤3:把n-1个圆盘(棕黄色)从B经过A移动到C
其中我们可以看到步骤2是没有经过其他柱子就移动到下一步的,而步骤1和步骤3移动到下一步的时候均经过了其他柱子。我们可以发现,步骤1和步骤3(n-1个圆盘)是比原问题(n个圆盘)规模小了1的同一问题,即步骤1和步骤3就是原问题递归的一个子问题。
代码实现
接下来由上述三个步骤对汉诺塔问题进行实现:
首先 在方法里定义4个参数,其中:n表示盘子的个数,a b c分别表示盘子所在的位置( 从左向右分别为起点,经过的位置,终点)
def hanoi(n,a,b,c):
if n>0:
hanoi(n-1,a,c,b)
# 步骤1:把n-1个圆盘从A经过C移动到B
print("moving from %s to %s" % (a,c))
# 步骤2:把第n个圆盘从A移动到C
hanoi(n-1,b,a,c)
# 步骤3:把n-1个圆盘从B经过A移动到C
hanoi(3,'A','B','C') #调用
调用时带入n=3运行代码进行验证,可得:
共七个步骤,与上面n=3时一致。
问题拓展
假设n个盘子移动需要h(n)次 , h(n)=h(n-1)+1+h(n-1)
可得:汉诺塔移动次数的递推式:h(n)=2h(n-1)+1
h(64)=18446744073709551615
假设婆罗门每秒钟搬一个盘子,则总共需要5800亿年~!