python之汉诺塔问题详解

#汉诺塔问题

  • 传说古老印度在一个圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片圣庙,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片,一次只移动一片,不管在哪根针上,小片必在大片上面。当所有的金片都从梵天穿好的那根针上移到另外一概针上时,世界就将在一声霹雳中消灭,梵塔、庙宇和众生都将同归于尽。
    hanoi
  • 游戏规则:从左到右 A B C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘子只能在小盘子的下面.
案例1
  • 只有一个盘子时,则直接有A,移动到C 完成。
案例2
  • 如果有两个盘子时,移动方案如下:
    A—>B #借助B,帮助C拿到最后一个盘子
    A—>C #最后一个盘子移动完成后,剩余的盘子已经全部到B上了
    B—>C #将剩余的盘子移动到C上,完成
案例3
  • 如果有三个盘子,盘子数量N = 3,移动方案如下:
    1
案例4
  • 如果有四个盘子,盘子数量N = 4,移动方案如下:
    2
    经过上面例子,我们可以发现如下规律:
  1. 当盘子只有一个是,即N=1,只有一个动作,从A移动到C即结束
  2. 当有N个盘子时:
    • 上半部分: 移动一定和n-1盘子移动时的动作相同。出发地都是A,只不过,n-1个盘子移动的目的是B,而不是C。这样方便取出最后一个盘子
    • 中间部分: 一定是由A移动到C
    • 下半部分: 此时等待移动的盘子已经都在B上,而不是A上,移动步骤类似于n-1个盘子的移动。出发地是B,目的地是C

递归分析

  1. 经过上面例子可以得到。如果想要移动n个盘子到指定目的,那么一定要先将n-1个盘子移动到备用柱上。
  2. 当n-1个盘子移动后,必定要将最后一个盘子移动到C上。
  3. 经过上面的调换后,剩下待处理的盘子还有n-1个,此时盘子已经在B上而不是在A上。此时需要从新判断剩余的盘子个数。如果依然大于1个那么还是需要按照1的步骤移动第n-1个盘子之上的所有盘子共n-2到A上。从而好让第n-1个盘子从B移动到C。
    总结:到第3步时,发现和有和第一步第二步类似地方。只需要改变盘子的出发点和目的点,就能刚好递归
对应的python实现如下:
def move(n,a,b,c):
    if n == 1: 
        print(a,"--->",c)
    else:
        move(n-1,a,c,b)
        print(a,"--->",c)
        move(n-1,b,a,c)
move(4,"A","B","C")

3

第二种类似方法
n=4
arr11 = arr1 = [_ for _ in range(n,0,-1)]
arr22 = arr2 = []
arr33 = arr3 = []
def move(n,arr1,arr2,arr3):
    if n==1: # 如果只有一个 移动方法一定是由arr1到arr3
        arr3.append(arr1.pop()) #arr1 移动的arr3
        print(arr11,arr22,arr33,"====",arr1,arr2,arr3) #打印,参考。
    else:
        move(n-1,arr1,arr3,arr2)  # 此时arr2为空元素,将n-1个元素移动到arr2中。
        arr3.append(arr1.pop()) # 将最后一个元素,移动到arr3中
        print(arr11,arr22,arr33,"====",arr1,arr2,arr3) #打印,参考
        # 此时,arr1,为空,而arr2里面有n-1个元素。重新调用递归,将剩余的元素移动到arr3中(此时剩余元素有n-1个)即,
        # 将arr2中的元素移动到arr3中。
        move(n-1,arr2,arr1,arr3)  
move(n,arr1,arr2,arr3)

4

  • 34
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值