找到规律, 化繁为简, 分而治之.
从小规模的问题开始, 逐渐增加问题的规模.
从人工完成问题的求解开始, 找到规律后, 再用程序自动化完成问题求解.
下面的结果示例中, 表示盘子的数字序列的左侧表示柱子的底部, 例如pillar1: [3, 2, 1].
1个盘子, 移动1次完成
pillar1: [1] pillar2: [] pillar3: []
pillar1: [] pillar2: [] pillar3: [1]
2个盘子,移动3次完成.
pillar1: [2, 1] pillar2: [] pillar3: []
pillar1: [2] pillar2: [1] pillar3: []
pillar1: [] pillar2: [1] pillar3: [2]
pillar1: [] pillar2: [] pillar3: [2, 1]
3个盘子,移动7次完成
pillar1: [3, 2, 1] pillar2: [] pillar3: []
pillar1: [3, 2] pillar2: [] pillar3: [1]
pillar1: [3] pillar2: [2] pillar3: [1]
pillar1: [3] pillar2: [2, 1] pillar3: []
pillar1: [] pillar2: [2, 1] pillar3: [3]
pillar1: [1] pillar2: [2] pillar3: [3]
pillar1: [1] pillar2: [] pillar3: [3, 2]
pillar1: [] pillar2: [] pillar3: [3, 2, 1]
4个盘子, 移动15次完成
pillarFrom: [4, 3, 2, 1] pillarB: [] pillarTo: []
pillarFrom: [4, 3, 2] pillarB: [1] pillarTo: []
pillarFrom: [4, 3] pillarB: [1] pillarTo: [2]
pillarFrom: [4, 3] pillarB: [] pillarTo: [2, 1]
pillarFrom: [4] pillarB: [3] pillarTo: [2, 1]
pillarFrom: [4, 1] pillarB: [3] pillarTo: [2]
pillarFrom: [4, 1] pillarB: [3, 2] pillarTo: []
pillarFrom: [4] pillarB: [3, 2, 1] pillarTo: []
pillarFrom: [] pillarB: [3, 2, 1] pillarTo: [4]
pillarFrom: [] pillarB: [3, 2] pillarTo: [4, 1]
pillarFrom: [2] pillarB: [3] pillarTo: [4, 1]
pillarFrom: [2, 1] pillarB: [3] pillarTo: [4]
pillarFrom: [2, 1] pillarB: [] pillarTo: [4, 3]
pillarFrom: [2] pillarB: [1] pillarTo: [4, 3]
pillarFrom: [] pillarB: [1] pillarTo: [4, 3, 2]
pillarFrom: [] pillarB: [] pillarTo: [4, 3, 2, 1]
要把k个盘子从pilla1, 移动到pilla3,
如果只有1个盘子, k=1时, 只需要
如果有k个盘子, k>1时, 需要
这样就把移动k个盘子的问题, 分解为2个移动k-1个盘子(问题变简单一些)和1次肯定能完成的移动(第k个盘从pilla1, 移动到pilla3上).
根据上面的规律编写程序.
import java.util.Stack;
public class HanoiTower {
static long counter = 0;
static Stack pillarFrom = new Stack();
static Stack pillarB = new Stack();
static Stack pillarTo = new Stack();
public static void hanoi(Stack pillar1, Stack pillar2, Stack pillar3, int moveAmount) {
if (moveAmount == 1) {
pillar3.push(pillar1.pop());
counter++;
printPillars();
} else {
hanoi(pillar1, pillar3, pillar2, moveAmount - 1);
pillar3.push(pillar1.pop());
counter++;
printPillars();
hanoi(pillar2, pillar1, pillar3, moveAmount - 1);
}
}
public static void main(String[] args) {
int amount = 6;
for (int i = 0; i < amount; i++) {
pillarFrom.push(amount - i);
}
printPillars();
hanoi(pillarFrom, pillarB, pillarTo, amount);
System.out.println("counter = " + counter);
}
public static void printPillars() {
System.out.printf(String.format("%-32s", "pillar1: " + pillarFrom.toString()));
System.out.print(String.format("%-32s", "pillar2: " + pillarB.toString()));
System.out.println(String.format("%-32s", "pillar3: " + pillarTo.toString()));
}
}
说明:
由于只能从最上面拿走1个盘子, pillar1, pillar2, pillar3用堆栈实现, 分别用静态变量pillarFrom, pillarB, pillarTo表示pillar1, pillar2, pillar3.
hanoi(Stack pillar1, Stack pillar2, Stack pillar3, int moveAmount)中的参数 pillar1, pillar2, pillar3在首次调用时表示 最初问题的pillar1, pillar2, pillar3; 在进行递归调用后, 表示在问题简化后的, 即由移动k个盘子的问题转化为移动k-1个盘子问题后的柱子 pillar1, pillar2, pillar3.
String.format("%-32s", "pillar1: " + pillarFrom.toString()) 是把字符串格式化为32个字符, 为了显示美观.
pillar1: [6, 5, 4, 3, 2, 1] pillar2: [] pillar3: []
pillar1: [6, 5, 4, 3, 2] pillar2: [1] pillar3: []
pillar1: [6, 5, 4, 3] pillar2: [1] pillar3: [2]
pillar1: [6, 5, 4, 3] pillar2: [] pillar3: [2, 1]
pillar1: [6, 5, 4] pillar2: [3] pillar3: [2, 1]
pillar1: [6, 5, 4, 1] pillar2: [3] pillar3: [2]
pillar1: [6, 5, 4, 1] pillar2: [3, 2] pillar3: []
pillar1: [6, 5, 4] pillar2: [3, 2, 1] pillar3: []
pillar1: [6, 5] pillar2: [3, 2, 1] pillar3: [4]
pillar1: [6, 5] pillar2: [3, 2] pillar3: [4, 1]
pillar1: [6, 5, 2] pillar2: [3] pillar3: [4, 1]
pillar1: [6, 5, 2, 1] pillar2: [3] pillar3: [4]
pillar1: [6, 5, 2, 1] pillar2: [] pillar3: [4, 3]
pillar1: [6, 5, 2] pillar2: [1] pillar3: [4, 3]
pillar1: [6, 5] pillar2: [1] pillar3: [4, 3, 2]
pillar1: [6, 5] pillar2: [] pillar3: [4, 3, 2, 1]
pillar1: [6] pillar2: [5] pillar3: [4, 3, 2, 1]
pillar1: [6, 1] pillar2: [5] pillar3: [4, 3, 2]
pillar1: [6, 1] pillar2: [5, 2] pillar3: [4, 3]
pillar1: [6] pillar2: [5, 2, 1] pillar3: [4, 3]
pillar1: [6, 3] pillar2: [5, 2, 1] pillar3: [4]
pillar1: [6, 3] pillar2: [5, 2] pillar3: [4, 1]
pillar1: [6, 3, 2] pillar2: [5] pillar3: [4, 1]
pillar1: [6, 3, 2, 1] pillar2: [5] pillar3: [4]
pillar1: [6, 3, 2, 1] pillar2: [5, 4] pillar3: []
pillar1: [6, 3, 2] pillar2: [5, 4, 1] pillar3: []
pillar1: [6, 3] pillar2: [5, 4, 1] pillar3: [2]
pillar1: [6, 3] pillar2: [5, 4] pillar3: [2, 1]
pillar1: [6] pillar2: [5, 4, 3] pillar3: [2, 1]
pillar1: [6, 1] pillar2: [5, 4, 3] pillar3: [2]
pillar1: [6, 1] pillar2: [5, 4, 3, 2] pillar3: []
pillar1: [6] pillar2: [5, 4, 3, 2, 1] pillar3: []
pillar1: [] pillar2: [5, 4, 3, 2, 1] pillar3: [6]
pillar1: [] pillar2: [5, 4, 3, 2] pillar3: [6, 1]
pillar1: [2] pillar2: [5, 4, 3] pillar3: [6, 1]
pillar1: [2, 1] pillar2: [5, 4, 3] pillar3: [6]
pillar1: [2, 1] pillar2: [5, 4] pillar3: [6, 3]
pillar1: [2] pillar2: [5, 4, 1] pillar3: [6, 3]
pillar1: [] pillar2: [5, 4, 1] pillar3: [6, 3, 2]
pillar1: [] pillar2: [5, 4] pillar3: [6, 3, 2, 1]
pillar1: [4] pillar2: [5] pillar3: [6, 3, 2, 1]
pillar1: [4, 1] pillar2: [5] pillar3: [6, 3, 2]
pillar1: [4, 1] pillar2: [5, 2] pillar3: [6, 3]
pillar1: [4] pillar2: [5, 2, 1] pillar3: [6, 3]
pillar1: [4, 3] pillar2: [5, 2, 1] pillar3: [6]
pillar1: [4, 3] pillar2: [5, 2] pillar3: [6, 1]
pillar1: [4, 3, 2] pillar2: [5] pillar3: [6, 1]
pillar1: [4, 3, 2, 1] pillar2: [5] pillar3: [6]
pillar1: [4, 3, 2, 1] pillar2: [] pillar3: [6, 5]
pillar1: [4, 3, 2] pillar2: [1] pillar3: [6, 5]
pillar1: [4, 3] pillar2: [1] pillar3: [6, 5, 2]
pillar1: [4, 3] pillar2: [] pillar3: [6, 5, 2, 1]
pillar1: [4] pillar2: [3] pillar3: [6, 5, 2, 1]
pillar1: [4, 1] pillar2: [3] pillar3: [6, 5, 2]
pillar1: [4, 1] pillar2: [3, 2] pillar3: [6, 5]
pillar1: [4] pillar2: [3, 2, 1] pillar3: [6, 5]
pillar1: [] pillar2: [3, 2, 1] pillar3: [6, 5, 4]
pillar1: [] pillar2: [3, 2] pillar3: [6, 5, 4, 1]
pillar1: [2] pillar2: [3] pillar3: [6, 5, 4, 1]
pillar1: [2, 1] pillar2: [3] pillar3: [6, 5, 4]
pillar1: [2, 1] pillar2: [] pillar3: [6, 5, 4, 3]
pillar1: [2] pillar2: [1] pillar3: [6, 5, 4, 3]
pillar1: [] pillar2: [1] pillar3: [6, 5, 4, 3, 2]
pillar1: [] pillar2: [] pillar3: [6, 5, 4, 3, 2, 1]
counter = 63