P1155 雙棧排序

2021-07-23 10:41:11 字數 1645 閱讀 5055

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希望知道其中字典序最小的操作序列是什麼。

輸入格式:

輸入檔案twostack.in的第一行是乙個整數n。

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

輸出格式:

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

可以發現,若有i < j < k,使得ak < ai < aj,那麼第i個元素和第j個元素自始至終不能進同乙個棧

可用反證法證明

把每個元素看成乙個點,那麼這個序列就變成一張二分圖,對其染色,最後模擬出棧即可

#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 1e3 + 10;

int n,now = 1,a[maxn],c[maxn],s[2][maxn],top[2];

vector v[maxn];

queue q;

void push(int x,int po)

if (!po)

else

s[po][++top[po]] = x;

printf("c "); }}

int main()

min = min(min,a[i]);

} for (int i = 1; i <= n; i++)

if (c[i] == -1)

continue;

} c[to] = c[k] ^ 1;

q.push(to);}}

} for (int i = 1; i <= n; i++)

push(a[i],c[i]);

while (top[0] && top[1])

while (top[0]) printf("b "),--top[0];

while (top[1]) printf("d "),--top[1];

return 0;

}

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...