汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。如图所示:
提示
这个问题看似复杂,其实不管 n 是多少,都可以归纳为三个步骤:
把 n-1个盘子从 A 移动到 B,此时 A 上只剩下最下面的一个盘子
直接把最后一个盘子从 A 移动到 C
把 B 上的 n-1 个盘子移动到 C 上
我们可以这样考虑——以上三个步骤包含下面两种操作:
把多个盘子从一个柱子上移动到另一个柱子上,以第三个柱子作为中介
把一个盘子从一个柱子直接移动到另一个柱子上于是我们可以用两个函数来分别实现上面两种操作——第二个函数可以直接一步实现,而第一个函数就需要用到递归调用了。
一开始考虑多个圆盘容易思维混乱,所以我们先缩小问题规模,从三个圆盘的基本问题开始思考,先找出三层汉诺塔的解法,如图3.8所示(注意:此图仅作为原理演示):
https://img-blog.csdn.net/20170515191145436?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzUxNzc1NzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
仔细思考三层汉诺塔的解法,就能找到解决多层汉诺塔问题的方法了。在来回移动的过程中,当发现有“在做重复相似的事情”的感觉的时候,其实就是潜在的解决问题的递归思路。保持这种感觉,让我们来理一理:
①②③中,移动三次将两个圆盘从a柱移到了b柱
⑤⑥⑦中,移动三次将两个圆盘从b柱移到了c柱
将上述的步骤合起来,就变为了两层汉诺塔的移动的步骤
如果仍存在困惑,你可以继续类比推导四层、五层等等的汉诺塔移动方法。
通过这种思考方法,我们总结一下n层汉诺塔的通用移动方法:
将n个圆盘从x柱,经由z柱中转,移到y柱(即解出汉诺塔移动方法)时:
当n=0时,
不用做任何动作。
当n>0时,
首先,将n-1个圆盘从x柱,经由y柱中转,移到z柱(解出n-1层汉诺塔),
然后,将1个圆盘从x柱移到y柱,
最后,将n-1个圆盘从z柱,经由x柱中转,移到y柱(解出n-1层汉诺塔)。
从以上步骤可知,要解出n层汉诺塔,需要使用n-1层汉诺塔的解法。
为了方便表示,我们将解出的n层汉诺塔所需要的最少移动次数表示为:H(n)
例如,移动0个圆盘的次数为0,则:H(0)=0
而移动1个圆盘的次数为1,则:H(1)=1
根据n层汉诺塔所用的步骤,则可以得到移动次数的递推公式:H(n)=H(n-1)+1+H(n-1) (n≠0n≠0)
因此题并不涉及,这里直接给出,有兴趣的读者可以自己再推下:H(n)=n2−1