引子
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
提示:以下是本篇文章正文内容,下面案例可供参考
一、解题思路
说简单点:就是把A上的n个圆盘全部移到C上,要求是,操作过程中ABC三个柱子从下往上,盘子依然是从大到小
我们先来看几种简单的情况:
n=1时:
A上只有1个圆盘,你直接移到C即可,我们用A->C表示
n=2时:
A上2个圆盘,我们把最上面的移动到B,然后A剩余1个圆盘,,再把A剩余圆盘移动到C,最后B移动到C,我们用A->B,A->C,B->C表示,如下图:
A->B
A->C
B->C
到这里完成n=2的目标。
n=3时:
示意图如下:
A->C
A->B
C->B
A->C
B->A
B->C
A->C
到这里n=3移植完毕。
注意:
在n=3时,我们可以发现,要从A移动3个盘子到C上,我们会经历2个盘子在B上的时候,如下图:
因为C上已经有最大的盘了,那这个时候问题就变成了,如何把B上2个盘子移动到C上,那不就是n=2时的操作吗?只不过这时B成了出发站,A成了中转站,C仍是目标站
我们用这个思路来看一看n=4的情况
我们想办法把最大盘移动到C,然后剩余3个盘依次移动到B,如上图。这时问题就转换成了,如何把三个盘子从下往上是从大到小的顺序移动到C,这时思路就和n=3一样了
至此,递归的思路就很清晰了:n个盘子的时候,将n-1个盘子移动到中转上,然后从起始位置把1个最大盘移动到目标位置上。
然后问题转换为:中转位置成为起始位置,原起始位置成为中转位置,目标位置仍是pos3,如何把起始位置上n-2个盘子移动到目标位置上?
。。。
二、实战代码
代码如下(示例):
public static void move(char pos1 ,char pos2) {
//模拟实现盘子的移动
//pos1移动到pos2,这里pos1、pos2只是一个代指
// 比如你想移动A上方的一个盘子到C,你传参就是pos1=A,pos2=B
System.out.print(pos1+"->"+pos2+" ");
}
public static void hanNuoTa(int n,char pos1 ,char pos2,char pos3) {
//n表示要移动的盘子个数
//pos1起始位置、pos2中转位置、pos3目标位置
//因为移动过程中,目标位置、中转位置是会变的
if(n==1)
{
move(pos1,pos3);
}
else
{
hanNuoTa(n-1,pos1,pos3,pos2);
//起始位置移动n-1个到中转位置
move(pos1,pos3);//n-1个移动完,将起始位置最大的1个移动到目标位置
//问题转换成:pos2是起始位置,pos3目标位置,pos1中转位置,如何将n-1个盘,从pos2移动到pos3
hanNuoTa(n-1,pos2,pos1,pos3);
}
}
public static void main(String[] args) {
hanNuoTa(1,'A','B','C');
System.out.println();
hanNuoTa(2,'A','B','C');
System.out.println();
hanNuoTa(3,'A','B','C');
System.out.println();
hanNuoTa(4,'A','B','C');
System.out.println();
}
关于下面代码的解释:
public static void hanNuoTa(int n,char pos1 ,char pos2,char pos3) {
//n表示要移动的盘子个数
//pos1起始位置、pos2中转位置、pos3目标位置
//因为移动过程中,目标位置、中转位置是会变的
if(n==1)
{
move(pos1,pos3);
}
else
{
hanNuoTa(n-1,pos1,pos3,pos2);
//起始位置移动n-1个到中转位置
move(pos1,pos3);//n-1个移动完,将起始位置最大的1个移动到目标位置
//问题转换成:pos2是起始位置,pos3目标位置,pos1中转位置,如何将n-1个盘,从pos2移动到pos3
hanNuoTa(n-1,pos2,pos1,pos3);
我们要从pos1移动n个盘去pos3,得先移动n-1个去pos2,全移动完后剩下一个大盘在pos1,我们移动到pos3;然后我们把pos2上的n-1个盘全移动到pos3即可完成
几组测试示例如下:
总结
汉诺塔问题理清脉络就是一个递归问题,上述方法设盘子数为n, n可为任意数,该法同样适用于移动n-1个盘。因此,依据上法,可解决n -1个盘子从A杆移到B杆(第一步)或从B杆移到C杆(第三步)问题。现在,问题由移动n个盘子的操作转化为移动n-2个盘子的操作。依据该原理,层层递推,即可将原问题转化为解决移动n -2、n -3… … 3、2,直到移动1个盘的操作,而移动一个盘的操作是可以直接完成的。