汉罗塔问题java数学模型(从数学原型到数学模型)
2017-10-28 23:56
495 查看
汉罗塔问题想必大家都知道了,然而今天我才第一次做,问题分类也很简单,递归,递归是很常用的算法,就是研究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。
那这样我们就知道移动的规律了,然后编程就很简单了(其实也没那么简单)
当n=5时是 232232
这个应该看出来了吧,递归不断调用自身是无限循环的,这样需要一个停止判断,就是if语句,但不是每个name(2)都可以结束整个循环的。
而是方法中的最后一个name(2)才结束方法,当方法中两个name(n-1)都完成时就会返回上一个值,理解这个模型的重点是知道方法中的每个方法都要到n=2时才结束循环,具体过程不debug是很难理解的,懂了原理i就好理解上面的具体的代码了,唯一要改的就是移动的对于顺序,写下来比较好懂一下(确定已经完全是做成了教学系列,不过自己也算学习了)
那先从简单的开始吧,首先我只用大脑只能推出前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。
那这样我们就知道移动的规律了,然后编程就很简单了(其实也没那么简单)
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); } }贴一下结果232423252324232
当n=5时是 232232
这个应该看出来了吧,递归不断调用自身是无限循环的,这样需要一个停止判断,就是if语句,但不是每个name(2)都可以结束整个循环的。
而是方法中的最后一个name(2)才结束方法,当方法中两个name(n-1)都完成时就会返回上一个值,理解这个模型的重点是知道方法中的每个方法都要到n=2时才结束循环,具体过程不debug是很难理解的,懂了原理i就好理解上面的具体的代码了,唯一要改的就是移动的对于顺序,写下来比较好懂一下(确定已经完全是做成了教学系列,不过自己也算学习了)
相关文章推荐
- 算法问题《Card Game》的数学模型和Java实现
- 用Java解决数学问题:将123456789分别填在[ ] [ ] [ ] [ ] ×[ ]=[ ] [ ] [ ] [ ]使等式成立,且数字不允许重复
- 钢管下料问题用非线性整数规划的数学模型来建模以及用Lingo进行计算
- 数学模型——线性规划问题
- 黑马程序员:Java基础总结----多重For循环的解决数学问题
- 把具体问题抽象成数学模型很重要!
- Java解决数学建模之席位分配问题
- 深入理解Java虚拟机笔记--JVM内存模型及溢出问题总结
- JAVA问题总结之7--Pow、sin、sqrt、abs等常用数学函数调用
- java中的数学乘法基础性问题
- 【0-1问题】 金矿模型 java实现
- 面试问题-使用Java线程做数学运算
- Java线程安全问题,方法及内存模型
- BITED数学建模七日谈之五:怎样问数学模型问题
- 《数学规划模型建立与计算机应用》系列:劳力规划问题
- 用JAVA程序解决鬼谷子数学问题
- 【JAVA基础】关于JAVA中的static方法、并发问题以及JAVA运行时内存模型
- 《数学规划模型建立与计算机应用》系列:工厂规划问题
- jvm住内存与工作内存,内存模型反映的java多线程问题
- java prototype原型模型模式讲解