Description
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
後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
Sample Input
Sample Output
解題思路:
畢竟是和漢諾塔有關,所以這道題在處理的時候首要的還是要理解清楚漢諾塔的原理。
因爲是已知的三個盤子的分佈列和總盤子的個數。所以我們從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;
}
}