算法 汉诺塔-java详解

来源:互联网 发布:网络机顶盒价格 编辑:程序博客网 时间:2024/05/16 07:24

第一次看到这个算法时,很懵逼,是在栈那里。想了半天没想到半点跟栈有关系的解法。最后看了答案,是用的递归。但是看了答案还是很懵逼,下面就是博主自己对汉诺塔的一些了解。


有三根木桩,第一根上有n个盘子,最底层的盘子最大,最上层的盘子最小。汉诺塔问题就是将所有的盘子从第一根木桩开始,以第二根木桩为桥梁,全部搬到第三根木桩。

不过在搬动时,尚须遵守以下游戏规则:

1、每次只能从最上面移动一个盘子(乍一看,尼玛还真是栈)

2、任何盘子可以从任何木桩搬到其他木桩。

3、直径较小的盘子永远必须放在直径较大的盘子之上。


下面的分析来源于其他博主

如果n=1,则将圆盘从A直接移动到C。如果n=2,则:1.将A上的n-1(等于1)个圆盘移到B上;2.再将A上的一个圆盘移到C上;3.最后将B上的n-1(等于1)个圆盘移到C上。  如果n=3,则:A. 将A上的n-1(等于2,令其为n`)个圆盘移到B(借助于C),步骤如下:(1)将A上的n`-1(等于1)个圆盘移到C上。(2)将A上的一个圆盘移到B。(3)将C上的n`-1(等于1)个圆盘移到B。B. 将A上的一个圆盘移到C。C. 将B上的n-1(等于2,令其为n`)个圆盘移到C(借助A),步骤如下:(1)将B上的n`-1(等于1)个圆盘移到A。(2)将B上的一个盘子移到C。(3)将A上的n`-1(等于1)个圆盘移到C。   到此,完成了三个圆盘的移动过程。    从上面分析可以看出,当n大于等于2时,移动的过程可分解为三个步骤:第一步  把A上的n-1个圆盘移到B上;第二步  把A上的一个圆盘移到C上;第三步  把B上的n-1个圆盘移到C上;其中第一步和第三步是类同的。

其实看到这里基本可以看出规律,就是用递归。

设盘数为n,

当n=1时,直接将盘从一号木桩转移到3号木桩

当n=2时,转移顺序:1号->2号,2号->3号,2号->3号

重点就是当n>=3时,将第n个盘和上面的n-1个盘分离,整体看起来就剩下2个部分:n,(1~n-1);后面递归就是将(1~n-1)分离成(1~n-2)和(n-1)...以此递归。

递归方法体面放四个参数,n(层数),p1(一号桩),p2(二号桩),p3(三号桩)。每次递归(一号桩)是初始位置,(三号桩)为目标位置

那么n>=3时递归顺序便是:

先创建方法:public static void solve(int n,int p1,int p2,int p3){....}

(1)将(1~n-1)分离放到(二号桩),这里就是(1~n-1)在(一号桩)(初始位置),(二号桩)就是(三号桩)(目标位置)

第一次递归代码:solve(n-1,p1,p3,p2),说到底,真正有用的参数只有3个,第1个、第2个、第4个;第三个参数就是打酱油的,你也可以认为是借助工具。

(2)将n转移到(三号桩),按规矩,应该是solve(n-1,p1,p2,p3);但是这里写了第一是个死循环,第二,n转移没有借助p2,所以默认他很自觉,自己到三号桩,直接

System.out.println("从"+p1+"移动到"+p3);

(3)将(1~n-1)从(二号桩)转移到(三号桩),方法看懂(1)的这里自然懂

solve(n-1,p2,p1,p3);


那么这题完整解法就是:

import java.util.Scanner;public class Hanoi {//p1为初始盘,p3为目标盘public static void solve(int n,int p1,int p2,int p3){if(n==1)System.out.println("从"+p1+"移动到"+p3);else{solve(n-1,p1,p3,p2);System.out.println("从"+p1+"移动到"+p3);solve(n-1,p2,p1,p3);}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();solve(n,1,2,3);}}

0 0
原创粉丝点击