汉罗塔问题java数学模型(从数学原型到数学模型)

汉罗塔问题想必大家都知道了,然而今天我才第一次做,问题分类也很简单,递归,递归是很常用的算法,就是研究n项和n-1项的关系,下面算是自己以一个没有经验的人第一次做的思路。(又是学习记录做成教程系列)

那先从简单的开始吧,首先我只用大脑只能推出前3组的移动过程,然后到4个盘子的时候基本就没有思路了,并不敢肯定之间的联系,过程一下想不出来,那就想结果吧。前几个都能推出来f(1)=1;f(2)=3;f(3)=7;然后就可以分析规律了。

开始分析一个盘子时,A直接移过去C;

两个盘子时,把A上面的小的放在B上,然后A下面的移到C,再然后B上面的移动到C; 然后是 三个盘子时,很明显也要进行过渡,这里过程不写了,下面有。所以这个时候就可以看出来了,2个盘子时,就是把A上面的放在B上,把A下面的放在C上,这个时候就变成了一个盘子的情况(只是AB的位置交换了);

然后是三个盘子的时候,也是先把A除了最下面的盘子放在B上(最小的两个),然后把最大的一个盘子放在C上,然后又变成了两个盘子的情况了。

所以有n个盘子的推测也出来了,先把n-1个盘子整体放在B上,然后把A最下面的盘子放在C上,所以移动总次数=n-1移动的次数+移动成该情况的次数+1(把最大的盘放在C)

f(n-1)这个就是简单的次数,那要移动成上面的步骤需要的次数理解也很简单眼中只留下n-1个盘子,忽略最大的那一个,把目的C换成目的B,那还是=f(n-1)

所以f(n)=2*f(n-1)+1,那么只用迭代就可以算出来了,也就是下面的第一个方法,但如果要移动过程就适合使用递归了,但递归的理解最好还是基于这个公式来做,为了便于理解找出规律贴上了,前4个盘子的情况。

这里检验一下上面的公式,这里分别是2,3,4个盘子的移动步骤,有下面三个规律(上面提过的就没写了):

  1.都是在f(n-1)的步骤将A的盘子(最大的那个)移动到C。

2.f(n)的前f(n-1)项和f(n-1)的对应项B和C是相反的,其他都是一模一样的。

3.f(n)的后f(n-1)项和f(n-1)的对应项A和B是相反的,其他都是一模一样的。

总结:前f(n-1)步的过渡盘是C,后f(n-1)步过渡盘是B。中间插了一步A到C。

《汉罗塔问题java数学模型(从数学原型到数学模型)》

那这样我们就知道移动的规律了,然后编程就很简单了(其实也没那么简单)

package test1;

public class Hanluota {
	int count = 0;
	
	public void index(int n) {
		int result = 0;
		for (int i = 0; i < n; i++) {
			result = result*2 +1;
		}	
		System.out.println("实际移动次数"+result);
	}
	
	//n为需要移动的盘子个数,a是起始位置,c是目的盘,b是过渡盘
	public void process(int n,char a,char b,char c) {
		if (n==1) {
			count++;
			System.out.println("第"+count+"步从" + a + " 移动盘子" + n + " 号到" + c);
			return;
		}	
		process(n-1, a, c, b); 		//过渡盘逐次交换,比如2,A,B,C是输入时,到这里是1,A,C,B,而n=2时第一步就是A-B,可以参考上面
		count++;
		System.out.println("第"+count+"步从" + a + " 移动盘子" + n + " 号到" + c);
		process(n-1, b, a, c);		//上面的n-1最后结束是1,return返回的n是上一个数2
	}	  
	  
	    public static void main(String[] args) { 
	    	Hanluota a1 = new Hanluota();
	        a1.process(4, 'A', 'B', 'C');   
	        a1.index(4);
	    }  
	}  

这个结果就不贴了,上面 有,但其实这个递归代码是属于一个常见的递归模型,不然是很难理解的,下面写了个类型一样的模型,这个模型的特点完全符合刚刚上面提到的三个规律,不然别的方法还真是想不到,试了次迭代,没成功。。。

package test;

public class digui {
	
	public void name(int n) {
		if (n==2) {
			return;
		}
		name(n-1);
		System.out.print(n-1+"\t");
		name(n-1);
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		digui a1 = new digui();
		a1.name(6);
	}
}

贴一下结果2
3
2
423
2
5
232
4
2
32

当n=5时是 232232

这个应该看出来了吧,递归不断调用自身是无限循环的,这样需要一个停止判断,就是if语句,但不是每个name(2)都可以结束整个循环的。

而是方法中的最后一个name(2)才结束方法,当方法中两个name(n-1)都完成时就会返回上一个值,理解这个模型的重点是知道方法中的每个方法都要到n=2时才结束循环,具体过程不debug是很难理解的,懂了原理i就好理解上面的具体的代码了,唯一要改的就是移动的对于顺序,写下来比较好懂一下(确定已经完全是做成了教学系列,不过自己也算学习了)

    原文作者: 汉诺塔问题
    原文地址: https://blog.csdn.net/m15682532244/article/details/78380822
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞