自我总结算法(三)

算法问题:

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

问题分析:

这个问题最开始我非常的感兴趣,总感觉终于有个东西让我好好的思考一下了,对于长久没有用过的大脑也是一种考验。我们首先设A,B,C为汉诺塔的三个柱子,然后我们要将圆盘从A通过B移动到C。最初我通过画图的过程想找到它的规律然后进行算法的编写。从最初的两个的移动,画到之后的五个的移动方式,这个过程可以说是非常的艰难,画完五个,把自己都画蒙圈了,不过我也发现了一些规律,比如它的移动的步数总是(2^n)-1,在每次多一个棋子移动的时候,最上面的三个移动方式总是可以保持一致,这样我便有了将他们最上层的三个绑到一块,看成一个整体来进行分析,从这个角度进行分析,发现可行性还是比较的高的,一层一层的进行分析,在脑子里运行这个过程,当然也是在想了很多天后吧,想明白了他的运行过程,每次我们都从A上面移动一个到空的到B然后我们按照之前的移动方式,把现在的C看成A,然后把A看成C,(原因:现在A最上方的圆盘比B和C 中的每一个圆盘都大,因此我们现在不管怎样往A上面移动,都不会出现小的在下)然后我们通过原有的移动方式,将C上的圆盘全部移动到了A上,这样C就变成了空的,我们就可以将B上的圆盘移动到C上,然后再把之前移动到A上的圆盘,移动到C上面,这样我们便进行了,一次将一个次大的圆盘从A上门面移动到C上面的过程,这句这个过程,写了如下的算法。

算法:

import java.util.*;
public class HannNuoTa {
	public static void Hannuo(int n,char A,char B,char C) {
		if(n==1) {
			move(A,C);
			return;
		}
		Hannuo(n-1,A,C,B);      
		move(A,C);
		System.out.println("-----------");
		Hannuo(n-1,B,A,C);       
	}
	public static void move(char A,char C) {
		System.out.println(A+"--->"+C);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HannNuoTa sc=new HannNuoTa();
		Scanner p=new Scanner(System.in);
		char A='A';
		char B='B';
		char C='C';
		int step=p.nextInt();
		Hannuo(step,A,B,C);
	}
}

算法分析:

我们在这个Hannuo函数中调用了两次本身就是为了使得输出的结果可以是(2^n)-1个,这样的双层的调用自己总是可以使我们得到类似于(2 ^n )-n这样的结果类型,如果你看了我前几个算法,你也可以发现,我最近的几个算法都在用这种形式的递归函数,这样的形式说白了,用起来就是很爽,很快乐。函数中我们定义了 A,B,C 这三个变量来当做是我们的塔,函数中最难理解的估计就是这一部分
Hannuo(n-1,A,C,B); move(A,C); Hannuo(n-1,B,A,C);
在这一部分,你的形参,实参没有搞明白的话估计会看不明白,我之前也在纠结这个地方,但最后还是想明白了要这莫写。这里我们先将B和C调换了位置然后进入下一层的递归中,在下一层的递归中或许你会产生这样的疑问,我现在的这个B和C还是上一层的B和C吗?答案是否定的。在第一层,我们是(A,B,C)然后进入这层递归变成(A,C,B)------>(这里我们是将实参赋值成:B=C,C=B)
在进入下一层时我们的形式参数还是(A,B,C)------>(这里我们将实参赋值成:C=B,B=C)这样的一个赋值过程,在这个赋值过程中我们不断地调换B,C的位置,然后进行算法的递归。在移动第N个大圆盘时,剩下的N-1个都比这个小,因此我们可以将具有N-1个圆盘的塔C看成塔A然后进行移动,在将塔C都移动到塔A时我们我们将原本先前第N个已经移动到塔B的圆盘移动到塔C,再将塔A上的前N-1个移动到塔C,这样我们便将第N个圆盘从塔A移动到了塔C。完成了对任意一个N圆盘的移动。
在兴趣的指引下我去查阅了相关的资料,查到这样的结果:当要移动的N=64时,传说中的世界末日的来临,我们算每次移动时间为一秒,所需时间为:T=2^64 -1=18,446,744,073,709,551,615步=584,942,417,355年26天7小时15秒,所需的时间如此之长,长到够计算程序员的单身时间了。(ps:在这说一下,我身边有很多程序员朋友,单身可撩,哈哈哈哈哈)。

                                                         -------------------lonrover
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值