汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上(如图找了张5个的,意思一样)。有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求打印移动的步骤。如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C。
分析:
以5个盘子为例,进行分析。
先将上面4个盘子看成一个整体,那么第一步,需要借助B柱子,将上面4个盘子放在B柱子上,然后将A柱子最底的第5个盘子放到C柱子上,如下图所示:
那么问题就依赖于B柱子上的4个盘子如何移动,也就是n-1个盘子如何从B移动到C上面,这个问题又依赖于3个盘子如何移动
最终,转化为1个盘子移动的问题,最终状态:
伪代码:
if(n==1)
第一个盘子直接从A移动到C
else{
先把前n-1个盘子从A借助C移动到B
把第n个盘子从A移动到C
再把前n-1个盘子从B借助A移动到C
}
java代码实现:
public class Hanoi {
public static void move(char a,char b){
System.out.println(a+"---->"+b);
}
public static void rechanoi(int num,char A,char B,char C){
//只有一个盘子
if(num==1)
move(A,C);
else{
/*
此处是A柱子上num-1个盘子借助C移动到B
*/
rechanoi(num-1,A,C,B);
move(A,C);
/*
将B柱子上的num-1个盘子借助A移动到C
*/
rechanoi(num-1,B,A,C);
}
}
public static void main(String[] args) {
System.out.println("盘子移动情况如下:");
rechanoi(3,'A','B','C');
}
以3个盘子为例进行演示:
盘子移动情况如下:
A---->C
A---->B
C---->B
A---->C
B---->A
B---->C
A---->C
递归方法的特征:
- 调用自身
- 当它调用自身的时候,它这样做是为了解决更小的问题
- 存在某个足够简单的问题的层次,在这一层算法不需要调用自身就可以直接解答,且返回结果
后记:当手动地解决这个难题时,有一个经验法则,可以提供帮助,如果试图要移动的子树含有奇数个盘子,开始时直接把最顶端的盘子移动到目标柱子上,如果试图要移动的盘子是偶数,那么开始要把最顶端的盘子移动到中介柱子上。