以前在学校搞蓝桥杯的时候遇到过这个问题,最近又碰到了,就复习一下
什么是汉诺塔问题?
引用 wikipedia 的解释
有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:
每次只能移动一个圆盘;
大盘不能叠在小盘上面。
提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
把三根杆子称为:
起始杆:圆盘最初所在的杆
中转杆:用于临时放圆盘的杆
目标杆:要把圆盘移到这里来
具体到编程就是
def move(n,a,b,c):
'''
n: 需要移动的圆盘数量
a: 起始杆
b: 中转杆
c: 目标杆
'''
pass
思路
如果只有一个盘
如果只有一个盘,不需要中转,直接从 A → C 即可
def move(n,a,b,c):
if n == 1:
print(a,'->',c)
如果有多个盘
两个盘时
将 起始杆 上的圆盘从上到下标记为 1,2
步骤1:将 1 从 A 移动到 B
步骤2: 将 2 从 A 移动到 C
步骤3: 将 1 从 B 移动到 C
三个盘时
将 起始杆 上的圆盘从上到下标记为 1,2,3
步骤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
我们可以把上面的步骤分为 3 个阶段
步骤1-4:将 3 移动到 C
步骤5-6:将 2 移动到 C
步骤7:将 1 移动到 C
如果更多盘呢?
我们来观察上面的 3 个阶段,不难发现,每一个阶段的任务其实就是
把当前没有放到目标杆的最大圆盘放到目标杆
所以其实每一步所执行的都是相同的内容,只是问题的规模更小了 —— 递归
那么为了实现 把当前没有放到目标杆的最大圆盘放到目标杆 就又需要 3 步:
把 A 上的圆盘从上至下命名为:1,2,3……,n-1,n
- 把 A 上的 从 1 到 n-1 移动到 B
- 把 A 上的 n 移动到 C
- 把 B 上的 从 1 到 n-1 移动到 C
def move(n,a,b,c):
'''
n: 需要移动的圆盘数量
a: 起始杆
b: 中转杆
c: 目标杆
'''
if n == 1:
print(a,'->',c)
else:
move(n-1,a,c,b) # 把 A 上的 从 1 到 n-1 移动到 B
move(1,a,b,c) # 把 A 上的 n 移动到 C
move(n-1,b,a,c) # 把 B 上的 从 1 到 n-1 移动到 C
因此,答案就出来了
Q.E.D.