题目:汉诺塔问题,更改规则,限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧。只能通过中间的塔,求当塔N层的时候,打印最优移动过程和最优移动总步数。
当塔只有两层时,最上层的塔记为1,最下层的塔记为2,则打印:
Move 1 from 左 to 中
Move 1 from 中 to 右
Move 2 from 左 to 中
Move 1 from 右 to 中
Move 1 from 中 to 左
Move 2 from 中 to 右
Move 1 from 左 to 中
Move 1 from 中 to 右
移动次数为:8
采用递归方法解决:
首先:当只剩下最上层的塔需要移动时,总的有两种情况:
1.两侧移动,从左侧移动到右侧,从右侧移动到左侧, 需要两步,例如左->右: 左->中, 中->右。打印Move 1 from 左 to 中 ,Move 1 from 中 to 右
2.两侧移动中间位置,只需一步
以上过程是递归地终止条件。
接下来,我们分析多层塔的情况:
如果剩下N层塔,从最上面到最下面为1~N,则有如下判断:
1.如果剩下的N层塔都在左边,希望向中间移动,则需要3步
1)将1~N-1移动到右边,交给递归实现
2)将N移动到中间
3)将1~N-1移动到中间,交给递归实现
其他几种如N层塔,在中移动到左 和 中到右,右到中,都是3步。
2.如果剩下的N层塔在左边,希望向右移动,需要5步
1)将1~N-1移动到右边,交给递归
2)将N移动到中间
3)将1~N-1从右->左,递归实现
4)N: 中->右
5)1~N-1 : 左->右 递归实现
代码:
package chapter_1;
/**
* 递归调用汉诺塔
*/
public class Solution6 {
public static int hanoiProblem1(int num, String left, String mid, String right){
if(num < 0){
return 0;
}
return process(num, left, mid , right, left, right);
}
private static int process(int num, String left, String mid, String right, 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 " + mid);
System.out.println("Move 1 from " + mid + " to " + to);
return 2; //移动两次
}
}
if(from.equals(mid) || to.equals(mid)){//起点或者终点为mid情况
//将N层 左->中,中->左, 中->右,右->中,
String another = (from.equals(left) || to.equals(left)) ? right : left;
/**
* 左->中: 1-N-1,left->right; N, left -> mid; 1-N-1 right->mid
*/
int part1 = process(num - 1, left, mid, right, from, another); //N-1 left->right
int part2 = 1; // N left->mid
System.out.println("Move " + num + " from " + from + " to " + to);
int part3 = process(num - 1, left, mid, right, another, to);
return part1 + part2 + part3;
}else {
int part1 = process(num-1, left, mid, right, from, to);
int part2 = 1;
System.out.println("Move " + num + " from " + from + " to " + mid);
int part3 = process(num -1, left, mid, right, to, from);
int part4 = 1;
System.out.println("Move " + num + " from " + mid + " to " + to);
int part5 = process(num - 1, left, mid, right, from, to);
return part1 + part2 + part3 + part4 + part5;
}
}
}