传说故事
传说印度的主神梵天在一个黄铜板上插了3根宝石针,并在其中一根针上从上到下按从小
到大的顺序串上了64个金片。梵天要求僧侣们把金片全部移动到另一根针上去,规定每次只能
移动一片,且不许将大片压在小片上。移动时可以借助第三根针暂时存放金片。梵天说,如果
这 64 个金片全部移至另一根针上时,世界就会在一声霹雳之中毁灭。这就是汉诺塔。
汉诺塔问题是函数递归学习必然会遇到的编程问题之一。思考该问题如何解决对自己编程思维大有裨益。
进入正题
将三根柱子编号为A,B,C,最初金片都在A上,问题是要将A上的所有金片移动到C上。
符号解释
(1)A–>B : 将一块金片从A移动到B。
(2)f(n) : n块金片从A移动到C所需的最小次数。
(3) f A → C ( n ) f_{A\rightarrow C}\left( n \right) fA→C(n) :将n块金片从A移动到C的具体移动过程,每一步的移动用(1)的符号表示。
问题一:当金片的数量为n个时,求移动金片的最小次数。
思路分析:
n的阶乘、斐波那契数列,这两个问题的递归式都十分明显,易于写出。如果我们也能找到汉诺塔问题的递推式问题便迎刃而解了。
先考虑最简单的情形。
当n=1时,显然只要移动一次。A–>C
f(1) = 1,这便是该递归问题的出口。
现在我们思考n>1时的情形
当把n-1块从A上拿走后,此时第n块便可以从A移动到C,因为第n块最大,所以这时C上只能有这最大的第n块,其余的n-1块都在B上。接下来我们要将B上的n-1块移动到C上,整个任务就完成了。
第一次是将n-1块从A移动到B,第二次是将n-1块从B移动到C,根据对称性可知,这两次移动的次数是相等的,且与将n-1块从A移动到C的次数也是相等的。
由此可列得递推式
f ( n ) = 2 f ( n − 1 ) + 1 f\left( n \right) =2f\left( n-1 \right) +1 f(n)=2f(n−1)+1
问题二:当金片的数量为n个时,求移动金片最小次数的具体移动过程。
我们依然用解决问题一的思路。
当把n-1块从A上拿走后,此时第n块便可以从A移动到C,因为第n块最大,所以这时C上只能有这最大的第n块,其余的n-1块都在B上。接下来我们要将B上的n-1块移动到C上,整个任务就完成了。
只是这时我们要考虑移动两次移动这n-1次金片的具体过程。
我先给出递推式
f A → C ( n ) = f A → B ( n − 1 ) + ( A → C ) + f B → C ( n − 1 ) f_{A\rightarrow C}\left( n \right) =f_{A\rightarrow B}\left( n-1 \right) +\left( A\rightarrow C \right) +f_{B\rightarrow C}\left( n-1 \right) fA→C(n)=fA→B(n−1)+(A→C)+fB→C(n−1)