1. 程式人生 > >洛谷——P1155 雙棧排序

洛谷——P1155 雙棧排序

是什麽 hellip das ron sta ash nbsp 壓入 front

題目描述

Tom最近在研究一個有趣的排序問題。如圖所示,通過2個棧S1和S2,Tom希望借助以下4種操作實現將輸入序列升序排序。

技術分享

操作a

如果輸入序列不為空,將第一個元素壓入棧S1

操作b

如果棧S1不為空,將S1棧頂元素彈出至輸出序列

操作c

如果輸入序列不為空,將第一個元素壓入棧S2

操作d

如果棧S2不為空,將S2棧頂元素彈出至輸出序列

如果一個1~n的排列P可以通過一系列操作使得輸出序列為1,2,…,(n-1),n,Tom就稱P是一個“可雙棧排序排列”。例如(1,3,2,4)就是一個“可雙棧排序序列”,而(2,3,4,1)不是。下圖描述了一個將(1,3,2,4)排序的操作序列:<a,c,c,b,a,d,d,b>

技術分享

當然,這樣的操作序列有可能有幾個,對於上例(1,3,2,4),<a,c,c,b,a,d,d,b>是另外一個可行的操作序列。Tom希望知道其中字典序最小的操作序列是什麽。

輸入輸出格式

輸入格式:

輸入文件twostack.in的第一行是一個整數n。

第二行有n個用空格隔開的正整數,構成一個1~n的排列。

輸出格式:

輸出文件twostack.out共一行,如果輸入的排列不是“可雙棧排序排列”,輸出數字0;否則輸出字典序最小的操作序列,每兩個操作之間用空格隔開,行尾沒有空格。

輸入輸出樣例

輸入樣例#1:
【輸入樣例1】
4
1 3 2 4
【輸入樣例2】
4
2 3 4 1
【輸入樣例3】
3
2 3 1

輸出樣例#1:
【輸出樣例1】
a b a a b b a b
【輸出樣例2】
0
【輸出樣例3】
a c a b b d

說明

30%的數據滿足: n<=10

50%的數據滿足: n<=50

100%的數據滿足: n<=1000

如果滿足 i<j<k &&num[i]<num[j],num[i]>num[k]就不能單棧排序並考慮雙棧

  如果 不是二分圖 就不能雙棧排序

最後模擬輸出 ————我居然在模擬上卡了很長時間!!

  1 #include <algorithm>
  2
#include <cstring> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 8 const int N(1000+15); 9 int n,num[N],pre,mi[N]; 10 11 int head[N],sumedge; 12 struct Edge 13 { 14 int u,v,next; 15 Edge(int u=0,int v=0,int next=0): 16 u(u),v(v),next(next){} 17 }edge[N<<1]; 18 void ins(int u,int v) 19 { 20 edge[++sumedge]=Edge(u,v,head[u]); 21 head[u]=sumedge; 22 } 23 24 int col[N],st1[N],st2[N],to1,to2; 25 void Paint_(int s) 26 { 27 col[s]=0; 28 queue<int>que; 29 que.push(s); 30 while(!que.empty()) 31 { 32 pre=que.front();que.pop(); 33 for(int i=head[pre];i;i=edge[i].next) 34 { 35 int to=edge[i].v; 36 if(col[to]!=-1) 37 { 38 if(col[to]==col[pre]) 39 { 40 puts("0"); 41 exit(0); 42 } 43 } 44 else 45 { 46 col[to]=col[pre]^1; 47 que.push(to); 48 } 49 } 50 } 51 } 52 53 int main() 54 { 55 scanf("%d",&n); 56 for(int i=1;i<=n;i++) 57 scanf("%d",num+i); 58 mi[n+1]=1e7; 59 for(int i=n;i>=1;i--) 60 mi[i]=min(mi[i+1],num[i]); 61 for(int i=1;i<n;i++) 62 for(int j=i+1;j<=n;j++) 63 if(num[i]<num[j]&&num[i]>mi[j+1]) 64 ins(i,j),ins(j,i); 65 memset(col,-1,sizeof(col)); 66 for(int i=1;i<=n;i++) 67 if(col[i]==-1) Paint_(i); 68 int now_min=1; 69 for(int i=1;i<=n;i++) 70 { 71 if(col[i]==0) 72 { 73 if(num[i]==now_min) 74 { 75 printf("a b "),now_min++; 76 if(st1[to1]==num[i]) to1--; 77 } 78 else if(!to1||st1[to1]>num[i]) 79 st1[++to1]=num[i],printf("a "); 80 for(;to1&&st1[to1]==now_min;) 81 printf("b "),to1--,now_min++; 82 } 83 else 84 { 85 if(num[i]==now_min) 86 { 87 printf("c d "),now_min++; 88 if(st1[to1]==num[i]) to1--; 89 } 90 else if(!to2||st2[to2]>num[i]) 91 st2[++to2]=num[i],printf("c "); 92 for(;to2&&st2[to2]==now_min;) 93 printf("d "),to2--,now_min++; 94 } 95 } 96 for(;now_min<=n;now_min++) 97 { 98 for(;st1[to1]==now_min;to1--) printf("b "); 99 for(;st2[to2]==now_min;to2--) printf("d "); 100 } 101 return 0; 102 }

洛谷——P1155 雙棧排序