hdu1997 漢諾塔VII(深度優先搜索)

Problem Description
n個盤子的漢諾塔問題的最少移動次數是2^n-1,即在移動過程中會產生2^n個系列。由於發生錯移產生的系列就增加了,這種錯誤是放錯了柱子,並不會把大盤放到小盤上,即各柱子從下往上的大小仍保持如下關係 : 
n=m+p+q
a1>a2>...>am
b1>b2>...>bp
c1>c2>...>cq
ai是A柱上的盤的盤號系列,bi是B柱上的盤的盤號系列, ci是C柱上的盤的盤號系列,最初目標是將A柱上的n個盤子移到C盤. 給出1個系列,判斷它是否是在正確的移動中產生的系列.
例1:n=3
3
2
1
是正確的
例2:n=3
3
1
2
是不正確的。
注:對於例2如果目標是將A柱上的n個盤子移到B盤. 則是正確的.
 
Input
包含多組數據,首先輸入T,表示有T組數據.每組數據4行,第1行N是盤子的數目N<=64.
後3行如下
m a1 a2 ...am
p b1 b2 ...bp
q c1 c2 ...cq
N=m+p+q,0<=m<=N,0<=p<=N,0<=q<=N,
 
Output
對於每組數據,判斷它是否是在正確的移動中產生的系列.正確輸出true,否則false 
 
Sample Input
6 3 1 3 1 2 1 1 3 1 3 1 1 1 2 6 3 6 5 4 1 1 2 3 2 6 3 6 5 4 2 3 2 1 1 3 1 3 1 2 1 1 20 2 20 17 2 19 18 16 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
 
Sample Output
true false false false true true
 
做這道題之前,我們首先應該知道的一個問題,漢諾塔問題代碼的原理是什麼?
假設一共有n個圓盤需要從最左邊的A杆移到最右邊的C杆,那我們把整個問題拆分,不就是這樣一個過程嘛:先將最下面的第n個圓盤與其他n-1個圓盤分開看。首先,將其他n-1個圓盤移到B圓盤,再把第n個圓盤移到C圓盤,最後將在B上的那n-1個圓盤集體移到C上就完成了整個過程。在這裏給大家張貼一段代碼,這個代碼也是最簡單的漢諾塔問題,即,如何將n個圓盤從最左邊的A杆移動到左右側的C杆,需要經歷怎樣的步驟,代碼如下:
//Hanoi Problem
#include<iostream>
using namespace std;
void Hanoi(int n,char A,char B,char C)
{
    if(1==n) ///如果A上只剩下1個圓盤的時候,直接把這個圓盤從A移到C即可
    {
        cout<<"從"<<A<<"移到"<<C<<endl;
    }
    else
    {
        Hanoi(n-1,A,C,B);///先將另外n-1個圓盤從A藉助C移動到B
        cout<<"從"<<A<<"移到"<<C<<endl;///第n個圓盤從A移到C
        Hanoi(n-1,B,A,C);///再將n-1個圓盤從B藉助A移到C
    }
}

int main()
{
    Hanoi(3,'A','B','C');
    return 0;
}
以上代碼的運行結果是(當然了,每次都是那對應杆上的最上面的那個圓盤):


而本題是這個問題的一個延伸,用的是深度優先搜索的方法,還有一些分治的思想。我們還是要從最下面的那個第n個圓盤入手,當你想將n個圓盤從A圓盤移動到C圓盤的時候,你得先將另外n-1個圓盤移動到B,再把A移動到C,這是最簡單的方式。因此,你肯定不能將第n個圓盤移動到B圓盤上,否則,就這道題而言就是不正確的。那另外兩種情況呢?
首先是第n個圓盤再A杆上,此時就是之前說的:其他n-1個圓盤移到B圓盤,再把第n個圓盤移到C圓盤,最後將在B上的那n-1個圓盤集體移到C上。
要是第n個圓盤再C上的話,你只需將另外在n-1個圓盤直接移到C上即可。

相關解釋,在代碼中已經給出瞭解釋:
#include<iostream>
using namespace std;

bool DFS(int n,int A[],int B[],int C[])///將n個圓盤從A杆藉助B杆從而移到C杆
{
    if(B[0]==n)///如果第n個盤在B杆上的話,就多步驟了,這是不正確的
    {
        return false;
    }
    else if(A[0]==n) ///如果第n個圓盤在A杆上
    {
        return DFS(n-1,A+1,C,B);///將第n個圓盤上方(所以是A+1)的n-1個圓盤藉助C移到B上
    }
    else if(C[0]==n) ///如果第n個圓盤在C杆上
    {
        return DFS(n-1,B,A,C+1);///將B上的n-1個圓盤藉助A移到C杆上,且在第n個圓盤的上方(所以是C+1)
    }
    return true;
}
int main()
{
    int A[70],B[70],C[70];
    int testNum;
    int n,m,p,q;
    cin>>testNum;
    while(testNum--)
    {
        cin>>n;
        cin>>m;
        for(int i=0;i<m;i++)
        {
            cin>>A[i];
        }
        cin>>p;
        for(int i=0;i<p;i++)
        {
            cin>>B[i];
        }
        cin>>q;
        for(int i=0;i<q;i++)
        {
            cin>>C[i];
        }

        if(DFS(n,A,B,C))
        {
            cout<<"true"<<endl;
        }
        else
        {
            cout<<"false"<<endl;
        }

    }
    return 0;
}


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