汉诺塔问题:
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。——百度百科
汉诺塔(Hanoi Tower)问题是一个经典的递归问题。该问题涉及到三个柱子和一些大小不一的圆盘。开始时,给定三根柱子,记为 A柱(初始柱),B(辅助柱),C(目标柱) ,其中 A 柱子上有 n 个盘子,从上到下编号为 0 到 n−1 ,且上面的盘子一定比下面的盘子小。
问:将 A 柱上的盘子经由 B 柱移动到 C 柱最少需要多少次?
要求:
- 每次只能移动一个圆盘。
- 圆盘只能放在柱子上或者从柱子上拿下。
- 任何时候,在某个柱子上的圆盘都必须保持大盘在下,小盘在上。
解题过程:(可以分为三步,以四层汉诺塔为例)
首先我们需要明白,想要将第四层圆盘放到C柱上就需要满足第一、二、三层圆盘需要按照要求放在B柱上,所以我们可以将上三层的汉诺塔当作一个整体:
1、最开始将除第四层以外的圆盘当作一个整体移动到B柱上。(第一步)
2、当整体移动到B柱上后,将第四层圆盘移动到C柱。(第二步)
3、将第四层圆盘移动到C柱后,将整体移动到C柱。(第三步)
在做完以上三步后,最大的圆盘就移动到了C柱上。
在第一步和第三步中,我们将除第四层以外的汉诺塔当作了一个整体进行移动。移动的本质是将其当作三层汉诺塔重复以上的三个步骤进行移动,而在移动第三层汉诺塔时,我们又可以将上两层当作一个整体进行移动,以此类推,这样就用到了递归的思想。
图示过程(以三层汉诺塔为例):
初始状态:
第一步:
详细步骤:(递归为两层汉诺塔问题,将B柱当作目标柱)
A柱 B柱 C柱
第二步:
第三步:
代码实现:
public static void main(String[] args) {
//递归求解汉诺塔问题
hanoi(3,'A','B','C');
}
//n为盘子个数,a为起始柱子,b为辅助柱子,c为目标柱子
public static void hanoi(int n,char a,char b,char c){
//剩一层汉诺塔时直接移动
if(n==1){
System.out.print(a+"->"+c+" ");
}else{
//将C柱(目标柱)当作辅助柱,先把上方的整体圆盘放置在B柱上
hanoi(n-1,a,c,b);
//将当前最大的圆盘从A柱放在C柱(目标柱)上
System.out.print(a+"->"+c+" ");
//最后将B柱上的整体圆盘放置在C柱上
hanoi(n-1,b,a,c);
}
}