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;否則輸出字典序最小的操作序列,每兩個操作之間用空格隔開,行尾沒有空格。
輸入樣例#1:
【輸入樣例1】輸出樣例#1:41 3 2 4
【輸入樣例2】
42 3 4 1
【輸入樣例3】
32 3 1
【輸出樣例1】30%的資料滿足: n<=10a b a a b b a b
【輸出樣例2】
0【輸出樣例3】
a c a b b d
50%的資料滿足: n<=50
100%的資料滿足: n<=1000
/*二分圖染色+模擬
1.首先考慮乙個簡單情況——單棧排序,顯然有這樣的乙個事實:
a[i]和a[j] 不能壓入同乙個棧?存在乙個k,使得i < j < k且a[k] < a[i] < a[j]
時間複雜度為o(n^3).對於n<=1000仍顯吃力,對此可以用動態規劃的思想,將上述複雜度降到o(n^2)。
狀態:f[i]=min(a[i],a[i+1], … ,a[n])
邊界條件:f[n+1]=inf;
狀態轉移方程:f[i]=min(f[i+1],a[i]);
於是上述判斷就轉化為了f[j+1] < a[i] && a[i] < a[j]
2.擴充套件到雙棧排序:
如果a[i]和a[j]不能在乙個棧內,即連線一條i與j之間的無向邊,接下來我們只需要判斷這個圖是否為二分圖
由於題目中說編號的字典序要盡可能的小,那麼就把編號小的盡可能放到stack1
判斷二分圖的方法可以採用黑白染色的方式,先從編號小的開始染,第乙個頂點染成黑色,相鄰的頂點染成不同的顏色,如果發現黑白衝突,那麼說明這個圖不是乙個二分圖,是不合法的,輸出0.
(dfs或bfs染色均可)
3.染色後所有黑色的點進stack1,所有白色的點進stack2,最後模擬輸出過程就可以了.
*/#include
#include
#include
#include
#define maxn 1001
using
namespace
std;
inta[maxn],v[maxn],f[maxn];
intq1[maxn],top1,q2[maxn],top2,now,l;
bool
ok[maxn][maxn];
intn;
void dfs(int x,int
y)
else
if(v[i]==0)dfs(i,y^1
); }
}int
main()
}
洛谷 P1155 雙棧排序
tom最近在研究乙個有趣的排序問題。如圖所示,通過2個棧s1和s2,tom希望借助以下4種操作實現將輸入序列公升序排序。操作a如果輸入序列不為空,將第乙個元素壓入棧s1 操作b如果棧s1不為空,將s1棧頂元素彈出至輸出序列 操作c如果輸入序列不為空,將第乙個元素壓入棧s2 操作d如果棧s2不為空,將...
洛谷P1155 雙棧排序 貪心
題目鏈結 首先不難想到一種貪心策略 能彈則彈,優先放a 然後xjb寫了寫發現只有 40 原因是存在需要決策的情況 比如 a b 現在進來乙個 7 看上去很難判斷 7 到底放在 如果放 a 後面來個 9 再來個 6 我們就涼了。但是如果先來的是 6 且此時已經排完了 1 5 那麼我們可以在後續操作中把...
P1155 雙棧排序
tom最近在研究乙個有趣的排序問題。如圖所示,通過2個棧s1和s2,tom希望借助以下4種操作實現將輸入序列公升序排序。操作a如果輸入序列不為空,將第乙個元素壓入棧s1 操作b如果棧s1不為空,將s1棧頂元素彈出至輸出序列 操作c如果輸入序列不為空,將第乙個元素壓入棧s2 操作d如果棧s2不為空,將...