汉诺塔(必考)
规则
- 每次只能移动一共盘
- 任何时刻都不能将大的圆盘放小圆盘上
- 满足1 2的情况下可以随便移动
- 目标:把a上的盘移到b
探索汉诺塔的规则
我们先从简单的1个盘,2个盘,3个盘来探索下汉诺塔的过程
假设圆盘在a柱上从上到下的初始编号为1~n
-
当个数为1时候 移动步骤为
- 第一步:1号盘 a->b
-
当个数为2时候 移动步骤为
- 第一步:1号盘 a->b
- 第二步:2号盘 a->c
-
当个数为3时候 移动步骤为
- 第一步:1号盘 a->b
- 第二步:2号盘 a->c
- 第三步:1号盘 b->c
- 第四步:3号盘 a->b
- 第五步:1号盘 c->a
- 第六步:2号盘 c->b
- 第七步:1号盘 a->b
规则如下:
- 奇数步骤(斜体) 最小的圆盘如下次序移动 a->b->c->a
- 偶数步骤:在其他两个塔之间把较小的圆盘移动 比如上次a->b 那么较小的一定是在a 所以a->c 如果上次c->a 下次一定c->b
知道了规则就轻轻松松了,思考下下面的步骤就行了
自顶向下思路:
- n个圆盘时候一定是分为三步
- 我们定义hannoi(n,a,b,c)的含义是把n个圆盘从a移动到c借助b
- 把a柱上面n-1个盘借助b移动到c
hannoi(n-1,a,c,b)
- 把a柱上最大的移动到b
Move(a,b)
- 循环1 2 两步 此时 n-1个最小盘在c上 我们只要把c当作a即可
hannoi(n-1,c,b,a)
python代码实现
"""
这里先定义一个二维的列表
方便以后打印输出过程
"""
n=3
a,b,c=['a',[3,2,1]],['b',[]],['c',[]]
def Move(a,b,is_print):#从a移动到b is_print 是否打印过程
a_ele=a[-1].pop()
b[-1].append(a_ele)
if is_print:
print("{} from {}--->{}".format(a_ele,a[0],b[0]))
def hanoi(n,a,b,c):#hanoi表示从a上的n个圆盘移动到b 借助c
if n>0:
hanoi(n-1,a,c,b)
Move(a,b,is_print=True)
hanoi(n-1,c,b,a)
hanoi(n,a,b,c)