用棧來求解漢諾塔問題
阿新 • • 發佈:2019-01-01
一、題目
漢諾塔問題比較經典,這裡修改一下游戲規則:現在限制不能從最左側的塔直接移動到最右側,也不能從最右側直接移動到最左側,而是必須進過中間。求當塔有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; } }
五、執行結果截圖: