hdu 1997 漢諾塔VII (DFS)

題目很有趣,平時認識的漢諾塔只是知道最少移動次數爲2^n-1,但對移動過程的細節考慮的比較少。想了半天,最後參考別人的思路求解的。感嘆其思路的精闢。

解題思路:

對一個含有n個盤子,從A柱移動到C柱藉助B柱的漢諾塔,第n個盤子移動到C柱過程是這樣子的:首先將其餘的n-1個盤子移動到B柱,然後第n個盤子直接移動到C柱。在這過程中,第n個盤子只出現在A柱和C柱兩個柱子上,也即第n個盤子不可能出現在B柱上。因此對於當前移動的盤子,只需檢查其所在的柱子是否符合這個要求,如果出現在B柱上,則顯然進入了錯誤移動中。這是本題求解思想精髓所在。漢諾塔是個遞歸求解過程,假設第n個盤子符合要求,則判別的下一個目標是第n-1個盤子。若第n個盤子在A柱上,此時剩餘n-1個盤子必由A柱移動到B柱,經由C柱。此時對第n-1個盤子,C柱就是其不可能出現的位置;若第n個盤子在C住上,這剩餘n-1個盤子則是在B柱上,經由A柱,移動到C柱上,因此,A柱就是第n-1個盤子不可能出現的位置。

根據漢諾塔遞歸求解的過程,對每個移動的盤子,可以用遞歸求解的方式判斷。代碼如下:


code:

#include<iostream>
using namespace std;

bool flag;
void DFS(int n,int *A,int *B,int *C){
    if(n==0){
        flag = true;
        return ;
    }
    if(B[0]&&n==B[1]){
        flag = false;
        return ;
    }
    if(A[0]&&n==A[1]){
        A[1]=A[0]-1;
        DFS(n-1,++A,C,B);
    }else if(C[0]&&n==C[1]){
        C[1]=C[0]-1;
        DFS(n-1,B,A,++C);
    }
}
int main(){
    int A[70],B[70],C[70];
    int T,n;
    cin>>T;
    while(T--){
        cin>>n;
        cin>>A[0];
        for(int i=1;i<=A[0];i++)
            cin>>A[i];
        cin>>B[0];
        for(int i=1;i<=B[0];i++)
            cin>>B[i];
        cin>>C[0];
        for(int i=1;i<=C[0];i++)
            cin>>C[i];
        DFS(n,A,B,C);

        if(flag)
        cout<<"true"<<endl;
        else
        cout<<"false"<<endl;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章