python学习笔记 // 以汉诺塔问题为代表的递归思想

Hanoi Tower问题

相传在古印度圣庙中,有一种被称为汉诺塔 Hanoi 的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置若干金盘(如下图 —— 图片来自百度百科 )。
在这里插入图片描述

游戏目标:

把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。

操作规则:

每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

分析解决:

或许我们可以很容易的想明白当只有2个或3个盘子时的解决办法,但当盘子数更多的时候,我们就很难具体列举出移动盘子的每一步,这时我们的常规思维便显得收效甚微,因此我们可以利用递归的思想来解决这个问题。

我们可以将汉诺塔问题进行简化,设共有n个盘子,我们可以把复杂的解决办法拆分为如下三个步骤:

  • 将 n - 1 个盘子从 A 杆移到 B 杆 ( 将除了最底部的那个盘子以外的所有盘子看作是一个整体 )
  • 将第 n 个盘子从 A 杆移到 C 杆 ( 最底部的那个盘子)
  • 将 n - 1 个盘子从 B 杆移到 C 杆

以此类推,我们可以将 n 个盘子的移动问题转化为 n - 1 个盘子的移动问题,再转化为 n - 2 个盘子的问题,最终转化为 1 个盘子的移动问题。

按照搬动规则,必须有三个柱子才能完成搬动,一个柱子作为搬动源,一个柱子作为搬动目的地,另一个柱子在中间过渡使用。在搬动过程中,三个柱子的作用是动态变化的,因此在函数中三个柱子必须指定,令其作为函数的参数。相关代码如下:

print("规则:将所有的盘子从a柱移到c柱\n")
while True:
    num = int(input("请输入盘子数:"))
    if (num <= 0):
        print("Error!")
        break
    count = 0
    def hanoi(num,a,b,c):
        global count
        if(num == 1):             #递归出口
            count += 1
            print("%d : %c -> %c" % (num,a,c))
        else:                     #递归式子
            hanoi(num-1,a,c,b)
            print("%d : %c -> %c" % (num,a,c))
            count += 1
            hanoi(num-1,b,a,c)
    hanoi(num,'a','b','c')
    print("需要移动的总次数为:%d\n" % count)

在这里插入图片描述

归纳总结:

递归的实质就是把问题进行简化,简化成形式相同、但较简单一些的情况,编写程序时只需要给出统一形式的递归式子,到运行时再由计算机逐层展开。程序中每经历一次递归,问题就得到进一步简化,不断的简化下去,直至抵达递归出口,就停止递归了。
在运用递归思想时,最重要的就是要时刻提醒自己,编写程序时只需要给出运算规律,具体实现细节应该让计算机去处理。千万不能钻到细节的实现中去,否则就会陷入实现细节的泥沼中很难理清头绪。

发布了12 篇原创文章 · 获赞 12 · 访问量 2972

猜你喜欢

转载自blog.csdn.net/qq_45805420/article/details/104117500