漢諾塔的非遞迴實現(25 分)
阿新 • • 發佈:2018-12-03
藉助堆疊以非遞迴(迴圈)方式求解漢諾塔的問題(n, a, b, c),即將N個盤子從起始柱(標記為“a”)通過藉助柱(標記為“b”)移動到目標柱(標記為“c”),並保證每個移動符合漢諾塔問題的要求。
輸入格式:
輸入為一個正整數N,即起始柱上的盤數。
輸出格式:
每個操作(移動)佔一行,按柱1 -> 柱2
的格式輸出。
//說說思路,根據網上對漢諾塔的總結,用stack完全模擬過程,即可得出答案。
//來自百度的解釋。
其實演算法非常簡單,當盤子的個數為n時,移動的次數應等於2^n – 1(有興趣的可以自己證明試試看)。後來一位美國學者發現一種出人意料的簡單方法,只要輪流進行兩步操作就可以了。首先把三根柱子按順序排成品字型,把所有的圓盤按從大到小的順序放在柱子A上,根據圓盤的數量確定柱子的排放順序:若n為偶數,按順時針方向依次擺放 A B C;
若n為奇數,按順時針方向依次擺放 A C B。
⑴按順時針方向把圓盤1從現在的柱子移動到下一根柱子,即當n為偶數時,若圓盤1在柱子A,則把它移動到B;若圓盤1在柱子B,則把它移動到C;若圓盤1在柱子C,則把它移動到A。
⑵接著,把另外兩根柱子上可以移動的圓盤移動到新的柱子上。即把非空柱子上的圓盤移動到空柱子上,當兩根柱子都非空時,移動較小的圓盤。這一步沒有明確規定移動哪個圓盤,你可能以為會有多種可能性,其實不然,可實施的行動是唯一的。
⑶反覆進行⑴⑵操作,最後就能按規定完成漢諾塔的移動。
輸入樣例:
3
輸出樣例:
a -> c a -> b c -> b a -> c b -> a b -> c a -> c
//用程式碼模擬百度給的搬運思路// #include<string> #include<iostream> #include<algorithm> #include<stack> using namespace std; int main() { stack < int > a,b,c; int i,j,n; cin>>n; char s[4]={'p','a','b','c'}; a.push(99999); b.push(999999); c.push(999999); for(i=n;i>=1;i--) { a.push(i); } if(n%2==1) { s[2]='c'; s[3]='b'; } for(i=1;;i++) { if(i%3==1) { printf("%c -> %c\n",s[1],s[2]); b.push(a.top()); a.pop(); if(b.size()==n+1||c.size()==n+1) break; if(c.top()>a.top()) { printf("%c -> %c\n",s[1],s[3]); c.push(a.top()); a.pop(); } else { printf("%c -> %c\n",s[3],s[1]); a.push(c.top()); c.pop(); } } else if(i%3==2) { printf("%c -> %c\n",s[2],s[3]); c.push(b.top()); b.pop(); if(b.size()==n+1||c.size()==n+1) break; if(b.top()>a.top()) { printf("%c -> %c\n",s[1],s[2]); b.push(a.top()); a.pop(); } else { printf("%c -> %c\n",s[2],s[1]); a.push(b.top()); b.pop(); } } else { printf("%c -> %c\n",s[3],s[1]); a.push(c.top()); c.pop(); if(b.size()==n+1||c.size()==n+1) break; if(c.top()>b.top()) { printf("%c -> %c\n",s[2],s[3]); c.push(b.top()); b.pop(); } else { printf("%c -> %c\n",s[3],s[2]); b.push(c.top()); c.pop(); } i=0; } // if(b.size()==n+1||c.size()==n+1) // break; } }