P1155 雙棧排序

2022-03-23 02:41:26 字數 1876 閱讀 7803

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)排序的操作序列:

當然,這樣的操作序列有可能有幾個,對於上例 (1,3,2,4), 是另外乙個可行的操作序列。tom希望知道其中字典序最小的操作序列是什麼。

輸入格式:

第一行是乙個整數n。

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

輸出格式:

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

輸入樣例#1: 

41 3 2 4

輸出樣例#1: 

a b a a b b a b

輸入樣例#2: 

42 3 4 1

輸出樣例#2: 

0輸入樣例#3: 

32 3 1

輸出樣例#3: 

a c a b b d

30%的資料滿足: n≤10

50%的資料滿足:n≤50

100%的資料滿足: n≤1000

解析:本題可採用「貪心法」分類討論。分為以下8個情況討論(if-else結構,每次迴圈只進行一種選擇):

(1)由於要最小字典序,當s1的top是我們需要的數時,直接彈出

(2)當s2的top是我們需要的數時,彈出

(3)當序列的第乙個數使我們需要的數時,壓入第乙個棧後馬上彈出

(4)當這個數和s1棧頂構成連續的數時(小於棧頂數),壓入s1

(5)當這個數和s2棧頂構成連續的數時(小於棧頂數),壓入s2

(6)當s1為空或棧頂小於當前數時,壓棧

(7)當s2為空或棧頂小於當前數時,壓棧

(8)如果以上操作均不可進行,證明當前序列不可雙棧排序,直接退出

詳見**:

1 #include2 #include3 #include4

using

namespace

std;

5 stacks1;

6 stacks2;

7int n,a[1001],s,now=1,l=1;8

char c[10000];9

intmain()

1016

while(now<=n)

1725

else

if(!s2.empty()&&s2.top()==now)

2631

else

if(a[l]==now)

3239

else

if(!s1.empty()&&s1.top()==a[l]+1)40

45else

if(!s2.empty()&&s2.top()==a[l]+1)46

51else

if(s1.empty()||s1.top()>a[l])

5257

else

if(s2.empty()||s2.top()>a[l])

5863

else

6468}69

for(int i=1;i<=s;i++)cout

70return0;

71 }

view code

P1155 雙棧排序

tom最近在研究乙個有趣的排序問題。如圖所示,通過2個棧s1和s2,tom希望借助以下4種操作實現將輸入序列公升序排序。操作a如果輸入序列不為空,將第乙個元素壓入棧s1 操作b如果棧s1不為空,將s1棧頂元素彈出至輸出序列 操作c如果輸入序列不為空,將第乙個元素壓入棧s2 操作d如果棧s2不為空,將...

P1155 雙棧排序

miku 規律 假如只有乙個棧,那麼如果原序列存在三個數x v y v x v z 那麼就不可能排序成功,但是這裡有兩個棧,那麼就應該把原序列分成兩部分 兩部分?二分圖。把不能在一起的點連邊,進行二分圖染色。如果成功,就意味著存在 兩個棧的成員搞定了 反之不存在 include include in...

P1155 雙棧排序

本來以為是一道排序題,然而看了一眼標籤 woc,圖論題,一臉懵逼 題意 給你兩個棧,四種操作 如果棧 s 1 如果輸入序列不為空,將第乙個元素壓入棧 s 2 用f i 維護字尾最小值 狀態 f i min a i a i 1 a n 邊界條件 f n 1 inf 狀態轉移方程 f i min f i...