第一次看到这个算法时,很懵逼,是在栈那里。想了半天没想到半点跟栈有关系的解法。最后看了答案,是用的递归。但是看了答案还是很懵逼,下面就是博主自己对汉诺塔的一些了解。
有三根木桩,第一根上有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);
}
}