汉诺塔
【问题】hanoi,也有翻译为河内塔的。据说是源于印度的古老传说。
传说大梵天创世之时,在其庙宇中,置3根金刚石的柱子。其中的一根柱子上叠放了64张大小各异的金盘。下面的金盘总是比上面的大。僧侣被要求把这些金盘完全搬到另一个空柱子上。但有如下约束:
- 每次只能搬一张金盘。
- 大的金盘不能放置在较小的金盘上面。
- 金盘如果不是在搬运的途中,就一定是套放在 3 个柱子中的一个上。
大梵天已预言,任务完成的时候,就是世界的末日。
请计算要完成此任务,最少需多少步移动?
显然,如果只有 3 个盘子,需要 7 次。
分析:
假设柱子为 a, b, c
现在 a 上有 n 个盘, b, c 都空着。
目标是把 a 上的盘搬到 c 去。
要完成这个目标,只要把除最后一张盘外的上面那些盘暂寄放在 b上,然后把最大的放到 c,再把 b 上的都搬到c。
对于除最后一张盘外的上面那些盘的移动,这最大的盘无论在哪里都不会造成阻碍,就好像那些盘是在空的柱子上折腾一样。因而,这是一个可以递归的问题。
### 汉诺塔
def hanoi(n):
if n==1: return 1
return 2 * hanoi(n-1) + 1
if __name__ == '__main__':
print(hanoi(64))
此题结果碰巧与【问题34】相同。
注意,这里给出的是移动的步数,并不是具体的移动方案。
如果要输出移动方案,那就需要给 3 根柱命名,传入参数时设计为: 从哪个柱,移到哪个柱,哪个柱为临时过渡用。
稍加设计,这个也是可以用递归来完成的。
### 汉诺塔具体移动方案
def hanoi(n, src, dst, tmp):
if n==1:
print("move 1 from {} to {}".format(src,dst))
return
hanoi(n-1, src, tmp, dst)
print("move {} from {} to {}".format(n,src,dst))
hanoi(n-1, tmp, dst, src)
if __name__ == '__main__':
print(hanoi(3,"a","b","c"))
其中,n为塔的规模。src为哪移走,dst为移到哪里,tmp为辅助柱。