汉诺塔
问题分析:
汉诺塔中有A,B,C三个柱子,A柱子上有n个上小下大的盘子。要求每次只能移动一个盘子且小盘子只能在大盘子上面,最终把A柱子上的盘子全部移动到C柱子上。
思考过程
- 假如只有一个盘子,那么直接将盘子从A移动到C。
- 如果有两个盘子,那么先将A柱子上的移动到B柱子,再将A柱子盘子移动到C柱子,再将B柱子盘子移动到C柱子。
- 第一步:
- 第二步:
- 第三步:
- 如果有三个盘子。我们可以将上面两个盘子看成一个整体,那么此时的问题便是两个盘子的子问题,这便涉及到了递归思路。如下图
- 此时,我们可以先将两个蓝色盘子看做整体。此时的问题便成了移动“两个”盘子。虽然题目要求每次只能移动一个盘子,但我们假设这两个蓝色盘子已经被我们成功移动到了我们想要的状态。此时,我们将可以按下图来移动:
- 第一步:
- 第二步:
- 第三步:
- 注意:我们仔细看第二步,我们假设A柱子上n-1个盘子都被我们移动到了想要的状态,那么整体的第二步便是将A柱子上最底下的盘子移动到C柱子上。第三步时候,是将B柱子上的整体盘子,移动到C柱子上,此时又是一个子问题,涉及到递归思路。其中第一步是将整体的盘子移动到B柱子,这也是递归思路。
- 如果有n个盘子,那么求n个盘子问题的子问题便是求n-1个盘子,求n-1个盘子问题的子问题便是求n-1-1个盘子…这是递归的重要思路体现。那么什么时候是个头呢?也就是递归的结束条件是什么呢?我们假想n-1-1-1-1…到1的时候,我们知道1个盘子直接从A柱子移动到C,这便是递归结束条件。
代码实现(Java)
package day4_10_14;
import java.util.Scanner;
/**
* @author:fover
* @date:2020/10/14 15:26
* @version:1.0
* @function:递归求解汉诺塔
*/
public class Home4 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请问有几个盘子:");
hanoTower(scanner.nextInt(),'A','B','C');
}
/**
* 汉诺塔
* @param n 盘子数目
* @param A 塔A
* @param B 塔B
* @param C 塔C
* @return
*/
public static void hanoTower(int n,char A,char B,char C) {
if (n == 1) {
Home4.move(1,A,C);
} else {
//递归,把塔A上1到n-1的盘子移动到A到B
hanoTower(n - 1,A,C,B);
Home4.move(n,A,C);
//递归,把塔B上1到n-1的盘子从B移动到C
hanoTower(n - 1,B,A,C);
}
}
public static void move(int disk,char M,char N) {
System.out.println("把"+disk+"号盘子从"+M+"移动到"+N);
}
}