HDU 1997 漢諾塔Ⅶ

 漢諾塔VII
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64d

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 



是正確的 
例2:n=3 



是不正確的。 
注:對於例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號盤子開始逆向往回判斷每一個盤子的位置是否正確。直到找到一號盤子或者出現不正確的盤子位置。

因爲在漢諾塔的解題思路是:第一步:將1~n-1 移到第二個盤子。第二步:把n移到第三個盤子。第三步:把1~n-1移到第三個盤子。

所以對於n個盤子的漢諾塔問題來說,第n個盤子只會出現在第一個盤子和最後一個盤子。

① n出現在第一個盤子時:n-1 只能處於第一個盤子(尚未移動)或者第二個盤子(等待n號盤子移動至第三個盤子)

② n出現在第三個盤子時:n-1 只能處於第二個盤子(等待從第二個盤子移動到三個盤子)或者第三個盤子(移動完畢)。

綜上,進行判斷即可判斷出每一步的盤子出現的位置是否正確。 



n = 4的時候漢諾塔的移動(如果不理解上面對於n-1位置的推測,可以分別看當n = 4時 3號的移動,n=3時 2號的移動):

             1: move 1 disk from A to B.
  2: move 2 disk from A to C.
  3: move 1 disk from B to C.
  4: move 3 disk from A to B.
  5: move 1 disk from C to A.
  6: move 2 disk from C to B.
  7: move 1 disk from A to B.
  8: move 4 disk from A to C.
  9: move 1 disk from B to C.
10: move 2 disk from B to A.
11: move 1 disk from C to A.
12: move 3 disk from B to C.
13: move 1 disk from A to B.
14: move 2 disk from A to C.
15: move 1 disk from B to C.


這道題,因爲自己在做的時候沒做出來,看了老師的代碼之後才做出來的。雖然代碼是自己寫的,但是和老師的代碼可以說完全一樣。


以下是AC代碼:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define fn(i,n) for(int i = 0; i < n; i++)
const int maxn = 64;
int num[3][maxn];
int n[3],p[3];//這兩個數組的0 1 2分別代表一二三號盤子,n數組是題目交代的各盤子上元素個數,p數組是盤子上已經確認位置正確的元素的位置

bool judge(int N, int fir, int sec, int thr){
    if(p[fir] < n[fir] && num[fir][p[fir]] == N){
        if(N == 1) return true;
        p[fir]++;
        return judge(N-1,fir,thr,sec);
    }
    else if(p[thr] < n[thr] && num[thr][p[thr]] == N){
        if(N == 1) return true;
        p[thr]++;
        return judge(N-1,sec,fir,thr);
    }
    else return false;
}

int main(){
    int T;
    cin >> T;
    while(T--){
        int N, ans;
        cin >> N;
        fn(i,3){
            cin >> n[i];
            fn(j,n[i]) cin >> num[i][j];
        }
        memset(p,0,sizeof(p));
        ans = judge(N,0,1,2);
        if(ans) cout << "true" << endl;
        else cout << "false" << endl;
    }
}


發佈了31 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章