1. 程式人生 > >用棧來求解漢諾塔問題

用棧來求解漢諾塔問題

一、題目

        漢諾塔問題比較經典,這裡修改一下游戲規則:現在限制不能從最左側的塔直接移動到最右側,也不能從最右側直接移動到最左側,而是必須進過中間。求當塔有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;
      }
}

五、執行結果截圖: