对于汉诺塔问题的递归解决

来源:互联网 发布:数据流程图类型 编辑:程序博客网 时间:2024/05/17 22:25

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



下面进行分析:(来自百度百科,我觉得解释得比我好)

让我们来考虑一下64个圆盘重新摞好需要移动多少次吧。1个的时候当然是1次,2个的时候是3次,3个的时候就用了7次......这实在是太累了
因此让我们逻辑性的思考一下吧。
4个的时候能够移动最大的4盘时如图所示。
到此为止用了7次。
接下来如下图时用1次,在上面再放上3个圆盘时还要用7次(把3个圆盘重新放在一起需要的次数)。
因此,4个的时候是
“3个圆盘重新摞在一起的次数”+1次+“3个圆盘重新摞在一起需要的次数”
=2x“3个圆盘重新摞在一起的次数”+1次
=15次。
那么,n个的时候是
2x“(n-1)个圆盘重新摞在一起的次数”+1次。
数据模型为:H(n) = 2H(n-1) +1, 然后很容易推断出此数列的通项为:H(n)=2^n-1
那么,从算法考虑,怎么实现呢?

算法:

当只有一个盘子的时候,只需要从将A塔上的一个盘子移到C塔上。
      当A塔上有两个盘子是,先将A塔上的1号盘子(编号从上到下)移动到B塔上,再将A塔上的2号盘子移动的C塔上,最后将B塔上的小盘子移动到C塔上。
      当A塔上有3个盘子时,先将A塔上编号1至2的盘子(共2个)移动到B塔上(需借助C塔),然后将A塔上的3号最大的盘子移动到C塔,最后将B塔上的两个盘子借助A塔移动到C塔上。
      当A塔上有n个盘子是,先将A塔上编号1至n-1的盘子(共n-1个)移动到B塔上(借助C塔),然后将A塔上最大的n号盘子移动到C塔上,最后将B塔上的n-1个盘子借助A塔移动到C塔上。
      综上所述,除了只有一个盘子时不需要借助其他塔外,其余情况均一样(只是事件的复杂程度不一样)。


用java语言实现就是:
public class Hanoi {static int count = 0;public void hanoi(int n,String from,String to,String depend){if(n == 1){move(from,to);}else{/**先把初始柱子的前n-1个盘子借助目标柱子移动到辅助柱子上**/hanoi(n-1,from,depend,to); /**然后把初始柱子上最后一个最大的盘,放到目标柱子上*/move(from,to);/**然后借助初始柱子(把初始柱子当成辅助柱子),把之前辅助柱子上的n-1个盘,放到目标柱子上*/hanoi(n-1,depend,to,from);/**由于是递归,反复调用,知道n=1,到递归出口*/}}public void move(String from,String to){System.out.println("from " + from + " to " + to);count++;}public static void main(String[] args) {/**定义ABC三个柱子,A为初始柱子,C为目标柱子,B为辅助柱子*/(new Hanoi()).hanoi(3, "A", "C", "B");System.out.println("一共移动了"+count+"步");}}
执行结果:
from A to C
from A to B
from C to B
from A to C
from B to A
from B to C
from A to C
一共移动了7步


原创粉丝点击