递归法实现汉诺塔问题
这里的汉诺塔问题稍加改动:从“左”不能直接到“右”,必须先从“左”到“中”,再从“中”到“右”;从“右”到“左”同理;即只能在相邻的柱子间移动。
思路:
process(int num, String from, String to)
函数,实现了第num
块,从from
柱子到to
柱子的移动过程- 移动分为两类,相邻柱子的移动,不相邻柱子的移动(如果是传统的汉诺塔问题则不用如此分类)
- 相邻柱子的移动:
从"左"到"中"
,从"右"到"中"
,从"中"到"左"
,从"中"到"右"
- 上面的
num - 1
层,从from
移到另一个柱子,即除了from
和to
的另一根柱子
- 然后第
num
块从from
到to
- 上面的
num - 1
层从另一个柱子到to
- 不相邻柱子的移动:
从"左"到"右"
,从"右"到"左"
- 上面的
num - 1
层从from
到to
- 第
num
块,从from
移到middle
- 然后第
num - 1
块从to
到from
- 第
num
块,从middle
移到to
- 上面的
num - 1
层从from
到to
package com.lilydedbb;
/**
* Created by dbb on 2016/12/24.
*/
public class HanoiProblemByRecursion {
private static String left = "left ";
private static String mid = "middle";
private static String right = "right ";
public static int hanoiProblem(int num){
if (num < 1)
return 0;
return process(num, left, right);
}
// 返回的是步数
public static int process(int num, String from, String to){
// 只有一个的时候
if(num == 1){
if(from.equals(mid) || to.equals(mid)){
System.out.println("move 1 from " + from + " to " + to);
return 1;
}else{
System.out.println("move 1 from " + from + " to middle");
System.out.println("move 1 from middle to " + to);
return 2;
}
}
// 从"左"到"中",从"右"到"中",从"中"到"左",从"中"到"右"
if(from.equals(mid) || to.equals(mid)){
String another = (from.equals(left) || to.equals(left)) ? right : left;
int part1 = process(num - 1, from, another);
int part2 = 1;
System.out.println("move " + num + " from " + from + " to " + to);
int part3 = process(num - 1, another, to);
return part1 + part2 + part3;
} else { // 从"左"到"右",从"右"到"左"
int part1 = process(num - 1, from, to);
int part2 = 1;
System.out.println("move " + num + " from " + from + " to middle");
int part3 = process(num - 1, to, from);
int part4 = 1;
System.out.println("move " + num + " from middle to " + to);
int part5 = process(num - 1, from, to);
return part1 + part2 + part3 + part4 + part5;
}
}
}
测试程序及测试结果如下:
int steps = HanoiProblemByRecursion.hanoiProblem(2);
System.out.println("The Minimum step is " + steps);
move 1 from left to middle
move 1 from middle to right
move 2 from left to middle
move 1 from right to middle
move 1 from middle to left
move 2 from middle to right
move 1 from left to middle
move 1 from middle to right
The Minimum step is 8
Process finished with exit code 0