用栈来求解汉诺塔问题

一、题目

        汉诺塔问题比较经典,这里修改一下游戏规则:现在限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须进过中间。求当塔有N层时候,打印最优移动过程和最优移总步数。

     例如,当塔数为两层时,最上层的塔记为1,最下层的塔记为2,如下图1所示:

           

                                                                 图1. 两层汉诺塔图

则打印:

  move 1 from left to mid

 move 1 from mid to right

  move 2 from left to mid

 move 1 from right to mid

  move 1 from mid to left

 move 2 from mid to right

  move 1 from left to mid

 move 1 from mid to right

It will move 8 steps.

二、要求

      用一下两种方法解决。

     (1)方法一:递归的方法;

     (2)方法二:非递归的方法,用栈来模拟汉诺塔的三个塔。

三、解答

   (1)方法一:递归的方法。(本篇博客主要介绍非递归方法,递归的方法就不贴代码了,网上有很多)

     (2)方法二:非递归的方法,用栈来解决。

四、可运行代码:

import java.util.Stack;

public class StackOfhanoiProblem {
      public static void main(String[] args) {
		 StackOfhanoiProblem s = new StackOfhanoiProblem();
		 int a = s.hanoiProblem(2, "left", "mid", "right");
		 System.out.println("It will move  "+a+"  steps.");
	}
      
       public enum Action{
    	   No,LToM,MToL,MToR,RToM          //描述四个动作:左到中,中到左,中到右,右到中
       }
      
      public static int hanoiProblem(int num,String left,String mid,String right) {
    	  Stack<Integer> ls = new Stack<Integer>();
    	  Stack<Integer> ms = new Stack<Integer>();
    	  Stack<Integer> rs = new Stack<Integer>();
    	  ls.push(Integer.MAX_VALUE);
    	  ms.push(Integer.MAX_VALUE);
    	  rs.push(Integer.MAX_VALUE);
    	  for(int i = num;i>0;i--) {
    		  ls.push(i);                //左侧栈模拟放着盘子,大的在下,小的在上
    	  }
    	  Action[] record = {Action.No};       
    	  int step = 0;
    	  while (rs.size() != num+1) {    //右侧栈如果存放的数量没有达到num+1时,说明没有全部移动过去,则执行循环
		 step += fStackTotStack(record, Action.MToL, Action.LToM, ls, ms, left, right);
		 step += fStackTotStack(record, Action.LToM, Action.MToL, ms, ls, mid, left);
		 step += fStackTotStack(record, Action.RToM, Action.MToR, ms, rs, mid, right);
		 step += fStackTotStack(record, Action.MToR, Action.RToM, rs, ms, right, mid);
		}
    	  return step;
      }
      
      public static int fStackTotStack(Action[] record,Action preNoAct,
    		  Action nowAct,Stack<Integer> fStack,Stack<Integer> tStack,
    		  String from,String to) {
    	  if(record[0]!=preNoAct && fStack.peek()<tStack.peek()) {
    		  tStack.push(fStack.pop());
    		  System.out.println("Move   "+tStack.peek()+"   from   "+from+"   to   "+to);
    		  record[0] = nowAct;
    		  return 1;
    	  }
    	  return 0;
      }
}

五、运行结果截图:







猜你喜欢

转载自blog.csdn.net/alan_gaohaodong/article/details/79301600