2.鐵軌
問題描述:
某城市有一個火車站。有n節(jié)車廂從A方向駛?cè)胲囌綜,按進(jìn)站順序編號為1~n。你的任務(wù)是判斷它們是否能按照某種特定的順序進(jìn)入B方向的鐵軌并駛出車站C。比如出棧順序(5,4,1,2,3)是不可能的,但是(5,4,3,2,1)是可能的。為了重組車廂,你可以借助中轉(zhuǎn)站C。這是一個可以停放任意多節(jié)車廂的車站,但由于末端封頂,駛?cè)隒的車廂必須按照相反的順序駛出C。對于每個車廂,一旦從A移入C,就不能再回到A了;一旦從C移入B,就不能回到C了。換句話說,在任意時刻,只有兩種選擇:A→C和C→B。
分析:
1.暴力求解:將進(jìn)棧順序為1,2,3,4,5的每一行種可能的出棧順序求解出來。耗費時間長,很可能不滿足時間復(fù)雜度的要求
2.逆向思維:我們可以根據(jù)出棧順序(B)來推出進(jìn)棧順序(A),思路如下:
將B的元素依次與A的元素和C的棧頂元素相比較:
- 1.若A=B則A→B;
- 2.若B=C則C→B;
- 3.若B!=C&&B!=A&&A!=empty則A→C;
- 4.若B!=C&&B!=A&&A=empty則沒有該輸出序列
#include<iostream>
#include<stack>
#include<cstdio>
using namespace std;
const int MAXN = 100;
int n;//入站的個數(shù)
int A[MAXN], B[MAXN];
stack<int> C;
int a = 0,b = 0;//記錄A,B的當(dāng)前元素
int main(){
scanf("%d", &n);
for(int i=0;i<n;i++){//輸入入站順序
scanf("%d",&A[i]);
}
for(int i=0;i<n;i++){//輸入出站順序
scanf("%d",&B[i]);
}
while(a<n){
if(C.empty()){
if(B[b] == A[a]){//A=B
cout<<"A→B"<<endl;
a++;
b++;
}
if(B[b] != A[a]){
cout<<"A→C"<<endl;
C.push(A[a]);
a++;
}
}
if(!C.empty()){
if(B[b]==A[a]){//A=B
cout<<"A→B"<<endl;
a++;
b++;
}
while(B[b]==C.top()){//B=C
cout<<"C→B"<<endl;
C.pop();
b++;
if(C.empty())break;
}
if(B[b]!=A[a] && C.top()!=B[b]){//A!=B&&B!=C&&A!=empty
cout<<"A→C"<<endl;
C.push(A[a]);
a++;
}
}
}
if(C.empty()){
cout<<"步驟如上"<<endl;
}else{
cout<<"沒有該輸出序列"<<endl;
}
return 0;
}
測試數(shù)據(jù):
5
1
2
3
4
5
5
4
3
2
1