汉诺塔问题

题目:汉诺塔问题,更改规则,限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧。只能通过中间的塔,求当塔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;
        }

    }
}

 

posted @ 2017-01-05 21:28  huangyichun  阅读(384)  评论(0编辑  收藏  举报