hdu1997 漢諾塔VII(DFS遞迴呼叫)
阿新 • • 發佈:2019-01-01
題目詳情:傳送門
我都要做鬱悶了,邏輯一直沒錯,但是最後一組答案就是過不了。看了幾個小時,終於發現問題所在了。我把陣列初始化 memset() 函式,放在了自定義函式 Input 中,使用形參的sizeof()作為地址的長度,結果陣列沒有初始化成功,導致悲劇的誕生。之後我把 memset() 中的地址長度改回陣列長度問題終於解決了。剛做這一題時我把它當成棧混洗了,結果一直沒琢磨明白。之後在網上一查,恍然大悟。霎時間,感覺好難過,為什麼自己就沒想到。下面我們來分析一下本題的思路吧。
分析:
這一題考查的遞迴的使用,又是一個以漢諾塔為載體的題目。用到遞迴那就要回歸到這個問題的本質:既然要最優解,那麼怎麼樣的才是最優解?如果你能想到這裡,那麼你就很接近成功了。其實要得到最優解的步驟其實只有三個:①先將第n個圓盤上的 n-1 個圓盤從 柱A 移動到 柱B ②將第n個圓盤從 柱A 移動到 柱C ③然後將之前的n-1個圓盤,再移到 柱C。通過這三個步驟,就可以以最優解的方式完成從 柱A 到 柱C 的移動。由此可見,要把n個圓盤從 柱A(藉助柱B)移動到 柱C,那麼一定要把第n個圓盤移動到 柱C,換而言之,就是 第n個圓盤一定是在 柱A 和 柱C 之間的,如果不在那麼肯定不是最優解。以此類推,要將n-1個圓盤從柱A(藉助柱C)移動到 柱B,那麼第 n - 1個圓盤 一定在 柱A 和 柱B 之間。到了這裡問題就基本解決了,剩下的就只有用你的雙手在鍵盤上飛舞就可以了。
本題程式碼如下:
#include <stdio.h> #include <string.h> #define MAXN 65 + 10 void Input(int *in_arr){ int i; memset(in_arr,0,MAXN*sizeof(int) ); scanf("%d",&in_arr[0]); for(i = 1; i <= in_arr[0]; i++) scanf("%d",&in_arr[i]); } bool hanoi(int n,int *a,int *b,int *c){ if(!n) //如果n等於0,那麼當然就是true return true; if( n == a[1] ) //如果第n個圓盤在柱A上,那麼就將 柱A 上的n-1個圓盤(除第n個圓盤以外的圓盤)通過 柱C 移動到 柱B 上 return hanoi(n-1,++a,c,b); else if(n == c[1]) //如果第n個圓盤在柱C上,那麼就將 柱B上的n-1個圓盤,通過柱A移動到柱B上 return hanoi(n-1,b,a,++c); return false; //否則返回false } int main(){ int T,n; int A[MAXN],B[MAXN],C[MAXN]; scanf("%d",&T); while(T--){ scanf("%d",&n); Input(A); Input(B); Input(C); if(hanoi(n,A,B,C)) printf("true\n"); else printf("false\n"); } return 0; }
(如有錯誤,歡迎指正,如有轉載請註明出處)