经典算法之汉诺塔求解问题

法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。

这就是所谓的汉诺塔问题,也称河内塔。如果柱子标为ABC,要由A搬至C,在只有一个盘子时,就将它直接搬至C,当有两个盘子,就将B当作辅助柱。如果盘数超过2个,将第三个以下的盘子遮起来,就很简单了,每次处理两个盘子,也就是:A->B、A ->C、B->C这三个步骤,而被遮住的部份,其实就是进入程式的递回处理。事实上,若有n个盘子,则移动完毕所需之次数为2^n - 1,所以当盘数为64时,则所需次数为:264- 1 = 18446744073709551615为5.05390248594782e+16年,也就是约5000世纪,如果对这数字没什幺概念,就假设每秒钟搬一个盘子好了,也要约5850亿年左右。

简单逻辑代码

public static void main(String[] args) {		
		hanoi(64,'A','B','C');		
	}	
	public static void hanoi(int n, char A, char B, char C) {		
		if(n == 1) {
			System.out.println("移动" + n +"个盘子从"+ A + "到" + C);
		}else {
			hanoi(n-1,A,C,B);
			System.out.println("移动" + n +"个盘子从"+ A + "到" + C);
			hanoi(n-1,B,A,C);
		}
	}			
通过递归的方式实现对盘子的移动。简单说

1个盘子 直接从A移动到C

2个盘子 将1号盘子从A移动到B,再将2号盘子从A移动到C,再将1号盘子从B移动到C
3个盘子 将1,2号从A移动到B,再将3号从A移动到C,再将1,2号从B移动到C

....

这就是递归的思想,考虑移动64个盘子,其实就是将前63个从A移动到B,将64号从A移动到C,接着思考63个盘子从B移动到C的问题,也就是将62个盘子从B移动到A,再将63号盘子从B移动到C....依次类推,完整代码如下:

 	 public static int COUNT =0;//标记移动次数
	 public static int NUMBER = 3;//圆盘的数量	 
	    //实现移动的函数
	    public static void move(int disks,String N,String M)
	    {
	        System.out.println("第" + ( ++COUNT ) +" 次移动 : " +" 把 "+disks+" 号圆盘从 " + N +" ->移到->" + M);
	    }
	    //递归实现汉诺塔的函数
	    public static void hanoi(int n,String A,String B,String C)
	    {
	        if(n == 1)//圆盘数只有一个时,只需将其从A<金柱>塔移到C<铜柱>塔
	            TowersOfHanoi.move(1, A, C);//将编号为1的圆盘从A<金柱>移到C<铜柱>
	        else
	        {//否则
	            hanoi(n - 1, A, C, B);//递归,把A<金柱>塔上编号1~n-1的圆盘移到B<银柱>上,以C<铜柱>为辅助塔
	            TowersOfHanoi.move(n, A, C);//把A<金柱>塔上编号为n的圆盘移到C<铜柱>上
	            hanoi(n - 1, B, A, C);//递归,把B<银柱>塔上编号1~n-1的圆盘移到C<铜柱>上,以A<金柱>为辅助塔
	        }
	    }
	    public static void main(String[] args) {	       
	        System.out.println("***************************************");
	        System.out.println("	经典算法之汉诺塔求解	");
	        System.out.println("***************************************");
	        TowersOfHanoi.hanoi(NUMBER, "金柱","银柱", "铜柱");
	        System.out.println(">>移动了" + COUNT + "次,把金柱上的圆盘都移动到了铜柱上");
	    }


运行效果截图


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值