2022年 11月 8日

python解决汉诺塔问题

         汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘

这里,我们把三根柱子分别命名为A、B、C。

其中A为起始柱,B为过度柱,C为结果柱( ABC只是命名不同,不需要一模一样。)

解决思路如下:

采用递归方法,要想解决n个圆盘的转移,先解决n-1个圆盘……

直到圆盘只剩下一个,即一定会有一步,使n-1个盘子移动到过度柱B,才能让最大的第n个盘子移动到C。

这时可以忽略第n个盘子了,使问题变成移动n-1(或者说是第n-1和n-2个)个盘子,从B经过A(新的过度柱)移动到C。

假如只有一个盘子:

A->C

假如有两个盘子:

A->B

A->C

B->C

假如有三个盘子:

A->C

A->B

C->B

A->C  #此时最大的盘子已经移动到C   接下来剩下的要从B经过A(新的过度柱)移动到C。

B->A

B->C

A->C

话不多说,代码如下:

  1. def hanoi(num, a, b, c): #从A经过B移动到C即要解决问题的整体思路
  2. if num > 0:
  3. hanoi(num - 1, a, c, b) #从A经过C移动到B 步骤1
  4. print("moving from %s to %s " % (a, c))
  5. hanoi(num - 1, b, a, c) #从B经过A移动到C 步骤2
  6. hanoi(3, 'A', 'B', 'C')

 思路比较简单,内部代码运行可能比较麻烦,感兴趣如下:

注意,函数并非一直向下执行,而是多次重复步骤1,直到n-1个盘子都从A经过C移动到B,

以上为例,当有3个盘子时:

进入函数 hanoi(3, A, B, C)

  • 执行函数层1步骤1

 hanoi(2, A, C, B)   #先将n-1个移动到B(由函数层1,进入函数层2)

(此时对于第二层 步骤1  hanoi(1, A, B, C),对于步骤2  hanoi(1, C, A, B)

  •                 执行函数层2步骤1

 hanoi(1, A, B, C)   #先将n-1个的上面的移动到C 以此类推(进入函数层3)

(此时对于函数层3 步骤1  hanoi(0, A, C, B),对于步骤2  hanoi(0, B, A, C)

当A上剩余最后一个,此时继续执行步骤1,再进入一层函数

  •                                 执行函数层3步骤1

 hanoi(0, A, C, B)  #(进入函数层4

由于if条件不成立,函数结束,返回上一层函数hanoi(0, A, B, C)的末尾,函数层3的步骤1结束,开始执行print函数,函数层3的%(a,c)参数受函数层2的影响

moving from A to C   #打印转移的第一步,把第一个移动到了C

  •                                 执行函数层3的步骤2

hanoi(0, A, C, B)  #(进入函数层4

由于if条件不成立,函数结束,返回上一层函数hanoi(0, A, B, C)的末尾,函数层3的步骤2结束,返回函数层2步骤一末尾,开始执行print函数,函数层2的%(a,c)参数受函数层1的影响

moving from A to

  •                 执行函数层2步骤2

hanoi(1, C, A, B)  方法与函数层2步骤1相同

执行函数层3步骤1 ,结束

print:moving from C to B

执行函数层3步骤2,结束

函数层2步骤2结束

执行函数层1步骤12之间的print函数 (受hanoi(3, A, B, C)影响 

 moving from A to C   (完成第n个的转移)

  • 执行函数层1步骤2(同上)

hanoi(2, B, A, C)   ( 步骤1hanoi(1, B, C, A)  步骤2hanoi(1, A, B, C) ,不再细写)

moving from B to A 

moving from B to

moving from A to C 

结束

moving from A to C 

moving from A to

moving from C to B

moving from A to C 

moving from B to A 

moving from B to

moving from A to C 

来道例题加深理解:

  1. class Solution(object):
  2. def hanota(self, A, B, C):
  3. n = len(A)
  4. self.move(n, A, B, C)
  5. def move(self, n, A, B, C):
  6. if n == 1:
  7. C.append(A.pop())
  8. else:
  9. self.move(n - 1, A, C, B)
  10. C.append(A.pop())
  11. self.move(n - 1, B, A, C)
  12. A = [2, 1, 0]
  13. B = []
  14. C = []
  15. Solution().hanota(A, B, C)
  16. print(C) # [2, 1, 0]