- 个人主页:我的主页
- 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
目录
前言
本文对经典问题汉诺塔运用递归分治思想进行分解,并用GO语言进行编码验证。
问题描述
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
移动时应注意两条规则:
(1) 一次只能移动一个盘子
(2)大的盘子不能压在小盘子上
问题分析
假设有三根柱子分别为A,B,C,n个圆盘初始在A柱上,要借助C柱移动到B柱上,圆盘从大到小依次编号为n, n - 1, …, 2, 1。
我们现在来拆解子问题:
(1) 如果要把最大的n 号圆盘移到B柱,先要将n - 1,…,1的圆盘移到C柱才可以;所以首先完成n-1个圆盘从A到C的移动,借助B;
(2) 将A柱上仅剩下的n号圆盘移动到B柱;这样就完成最大圆盘的移动,它就不再移动;
(3) 现在的情况是n-1,…, 1的圆盘在 C 柱上,问题就变成了将n - 1,…, 1的圆盘从C柱移动到B柱上,借助A柱;
直到所有圆盘移动到B柱上;
问题延伸
要经过多少步移动才能完成呢? 有没有方法花费更少的步骤呢?下面我们来看一看。
假设有n片,移动次数是f(n)。这样就有f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2n-1 。
当n=64时,需要18446744073709551615次移动步骤,假如每秒钟一次,共需多长时间呢?一个平年365天有31536000秒,闰年366天有31622400秒,平均每年31557600秒,计算一下:18446744073709551615秒
移完古老传说中的这些金片需要5845.42亿年以上,几乎一切都不覆存在了。
算法实现
package main
import (
"fmt"
)
var count = 0
func Move(n int, A string, B string) {
count ++
fmt.Println("move ",n," from ", A, " to ",B)
}
func Hanoi(n int, A string, B string, C string) {
if( n > 0) {
Hanoi(n - 1, A, C, B)
Move(n, A, B)
Hanoi(n - 1, C, B, A)
}
}
func main() {
n := 3
Hanoi(n, "A", "B", "C")
fmt.Println("hanoi A->B, f(",n,")=",count)
}
结尾
作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!