背景
汉诺塔,又称河内塔(hanoi),源于印度古老的传说。
该传说中要求在三个柱子间移动金质的圆盘,规则是:
- 每次只能移动一个盘子
- 大盘子不能放在小盘子的上方
- 开始的时候,在某根柱子上有 n 个盘子,另两柱空着
题目
三根柱子编号 0, 1, 2
在 0 号柱子上有 n 个盘子,可以用 list 表示 [5, 4, 3, 2, 1]
数字的大小表示盘子的大小,List 尾为柱子的上端
今,要把 0 号柱的所有盘子最终移动到 2 号柱
请打印出移动的过程,以及过程中每个柱子的状态。
分析
题目看着好像挺不好处理
如果,只是问需要移动几次,还好办点。
其实不困难。
比如,要求把 n 个盘 从 a 柱移动到 c 柱,
这里的 n , a, c 都是变量。
那么,只需要:
- 先设法把上边的 n-1 个盘从 a 柱暂时放到 b 柱
- 再把最大的一个盘从 a 移动到 c
- 再设法把 n-1 个盘从 b 柱移动到 c
注意,b是个变量,与 a, c 有什么关系呢?
其实很简单: b = 3 - a - c
全部秘密就这么多了,上代码
代码
# 汉诺塔
def hanoi(n):
da = [[], [], []]
da[0] = list(range(1,n+1))
da[0].reverse()
print(da)
# 把 n 盘子从 a号柱移动到 b号柱
def f(a, b, n):
if n == 1:
da[b].append(da[a].pop())
print(a, ' -> ', b, ' : ' , da)
return
c = 3 - a - b
f(a, c, n-1)
f(a, b, 1)
f(c, b, n-1)
f(0, 2, n)
################
hanoi(3)
这是 n = 3 时的情景,运行效果是:
[[3, 2, 1], [], []]
0 -> 2 : [[3, 2], [], [1]]
0 -> 1 : [[3], [2], [1]]
2 -> 1 : [[3], [2, 1], []]
0 -> 2 : [[], [2, 1], [3]]
1 -> 0 : [[1], [2], [3]]
1 -> 2 : [[1], [], [3, 2]]
0 -> 2 : [[], [], [3, 2, 1]]
还是有疑惑?
去看视频吧,如下:
汉诺塔的移动步骤
祝编程愉快!