Published on

汉诺塔问题(A,B,C三根柱子 0,1,2,3,4五个圆盘)

Authors
  • avatar
    Name
    Pony Ma
    Twitter

A,B,C三根柱子 0,1,2,3,4五个圆盘

分治思想,把问题简化,拆分成子问题

我们只关注4号盘,要做的很简单,把0,1,2,3当做一个整体X,把X移到B柱(步骤一),4移到C柱(步骤二),再将X以到C柱(步骤三),结束

我们再来关注步骤一,刚才的整体X,再把他拆分,把0,1,2当做整体Y,把Y移动到C柱(步骤一),3移到到B柱(步骤二),再把Y移到到B柱(步骤三),结束

我们再来关注上述的步骤一,以此类推

拆分到最小的问题,就是只移动0号盘,移动一次即可就位

二进制解法

二进制简介

不管是怎么的进制,他们都是自相似的,规律都是一致的 重复计数若干次,进一位,再重复,再进一位

二进制只有两个数字0,1,它们叫bits(即二进制数位binary digits的简称) 我们从0开始数,当你数完0和1之后,bits就用完了,就要进到第二位,变成10 继续数,下一个是11,再继续,再次进位变为100

具体解法

用二进制来数数,计数的节奏就是解法 汉诺塔的算法和二进制计数都是自相似的过程

拆分到最小的问题,就是只移动0号盘,移动一次即可就位,这和二进制的计数规则是一致的,计数加一就需要进位,即进位到下一个圆盘

数第一位,第一位数字变化,就移动0号盘 数到第二位时,第二位数字变化,移动1号盘,第一位数字变化,就移动0号盘 数到第三位时,第三位数字变化,移动2号盘,第二位数字变化,移动1号盘,第一位数字变化,就移动0号盘

依次类推 第n位数字变化,就移动第n-1个盘

def solve_toh(n_disks):
   if n_disks == 0:
       return
   solve_toh(n_disks - 1)
   move_disk(n_disks - 1)
   solve_toh(n_disks - 1)
===========================
def move(n, a, b, c):
   if n == 1:
       print(a, '-->', c)
       return

   # 把n-1个盘子从a移动到b
   move(n - 1, a, c, b)

   # 把最底下的盘子从a移动到c
   move(1, a, b, c)

   # 把n-1个盘子从b移动到c
   move(n - 1, b, a, c)
move(3, 'A', 'B', 'C')

汉诺塔加强版

每次只能把圆盘移动到相邻的柱子上

实际原理也是一样的 我们只关注4号盘,把0,1,2,3当做一个整体X,把X移到B柱(步骤一),把X移到C柱(步骤二),4移到B柱(步骤三),再将X以到A柱(步骤四),4移到C柱(步骤五),再将X以到C柱(步骤六),结束

三进制解法

拆分成最小问题,即0号盘需移动两次才能就位 和三进制的计数方法是一致的,计数加二需要进一位,即进到下一个盘