列車排程(Train)習題精解與注意事項
題目:
描述 某列車排程站的鐵道聯接結構如Figure 1所示。
其中,A為入口,B為出口,S為中轉盲端。所有鐵道均為單軌單向式:列車行駛的方向只能是從A到S,再從S到B;另外,不允許超車。因為車廂可在S中駐留,所以它們從B端駛出的次序,可能與從A端駛入的次序不同。不過S的容量有限,同時駐留的車廂不得超過m節。
設某列車由編號依次為{1, 2, ..., n}的n節車廂組成。排程員希望知道,按照以上交通規則,這些車廂能否以{a1, a2, ..., an}的次序,重新排列後從B端駛出。如果可行,應該以怎樣
的次序操作?
輸入 共兩行。
第一行為兩個整數n,m。
第二行為以空格分隔的n個整數,保證為{1, 2, ..., n}的一個排列,表示待判斷可行性的駛出序列{a1,a2,...,an}。
輸出 若駛出序列可行,則輸出操作序列,其中push表示車廂從A進入S,pop表示車廂從S進入B,每個操作佔一行。
若不可行,則輸出No。
樣例 Example 1 Input
5 2 1 2 3 5 4 Output
push pop push pop push pop push push pop pop Example 2 Input
5 5 3 1 2 4 5 Output
No
限制 1 ≤ n ≤ 1,600,000
0 ≤ m ≤ 1,600,000
時間:2 sec
空間:256 MB
思路:使用一維陣列和int型別的指標模擬棧的基本操作,再設另一變數i作為入棧序列1,2,...n中的任意一個並不斷自增,若i不大於出棧序列out中的元素t,則入棧並判定棧是否空(m=0的情況),若空則out不可行。若i>t,則若判定棧非空且棧頂元素為t,出棧,反之out不可行。再定義一個一維陣列,元素為0為pop,1為push,時刻“記錄”每次出棧或入棧的操作,最後根據可行標誌輸出。注意:運算元最多為輸入數的2倍。
#include<cstdio> #define MAXSIZE 1600001 int stack[MAXSIZE],op[2*MAXSIZE];//定義棧和標記操作的陣列,注意全域性陣列元素為0 int i=1,j,k=0,m,n,t,flag=1,top=-1;//i為1,2,...n,k為陣列下標,flag標識序列可行性 void Judge(){ if(top!=-1&&stack[top]==t){//若棧非空且棧頂元素為t top--;//出棧 k++; } else flag=0; } int main(){ scanf("%d%d",&n,&m); while(n--){ if(!flag)break; scanf("%d",&t); if(i<=t){//說明t未入棧,需要入棧 for(;top<m-1&&i<=t;i++)//將i到t入棧,注意top從-1開始,故top需小於m-1 { stack[++top]=i;//入棧 op[k++]=1;//1為push,0為pop } Judge(); } else Judge(); } if(flag){//若序列可行,輸出 for(i=0;i<k;i++) if(op[i]) puts("push"); else puts("pop"); } else puts("No"); return 0; }