【每日一题】8月7日题目精讲—双栈排序
來源:牛客網
文章目錄
- 題目描述
- 題意:
- 題解:
- 代碼:
題目描述
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希望知道其中字典序最小的操作序列是什么。
輸入描述:
第一行是一個整數n。
第二行有n個用空格隔開的正整數,構成一個1~n的排列
輸出描述:
共一行,如果輸入的排列不是“可雙棧排序排列”,輸出數字0;否則輸出字典序最小的操作序列,每兩個操作之間用空格隔開,行尾沒有空格。
示例1
輸入
復制
輸出
復制
示例2
輸入
復制
輸出
復制
示例3
輸入
復制
輸出
復制
備注:
30%的數據滿足:n<=10 50%的數據滿足:n<=50 100%的數據滿足:n<=1000題意:
有四種操作,問如何操作可以實現將輸入序列升序排序
四種操作分別是:
操作a:如果輸入序列不為空,將第一個元素壓入棧S1
操作b:如果棧S1不為空,將S1棧頂元素彈出至輸出序列
操作c:如果輸入序列不為空,將第一個元素壓入棧S2
操作d:如果棧S2不為空,將S2棧頂元素彈出至輸出序列
題解:
貌似二分圖可以做(不過我還沒看懂)
首先推出規律:
如果兩個數 i,j(i≤j)i,j(i≤j) 不能被放入同一個棧中,當且僅當存在 k,k>jk,k>j, 且 q[k]<q[i]<q[j]q[k]<q[i]<q[j]。
現在有兩個棧,我們只需要將滿足這個條件的點各自歸到一邊,中間連一條線,用經典的染色法判斷是否為二分圖,若是則按照顏色入棧,
若不是則說明不能完成
代碼:
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<stack> #include<cmath> #define maxn 1004 using namespace std;const int inf=19260817; int n,num; int color[maxn]; int t[maxn]; //要排序的元素的存儲 int s[maxn]; //判斷兩個數字是否滿足規則 bool flag,e[maxn][maxn];void paint(int x,int c){ //DFS進行染色color[x]=c;for(int i=1;i<=n;i++){if(e[x][i]){ //查找相鄰點 if(color[i]==c) flag=false; //若相鄰點顏色相同,則錯誤if(!color[i]) paint(i,3-c); //若未染過色,對其染色,3-c結果為1,2,表示1與2號棧}} }void make(){ //創造二分圖s[n+1]=inf; for(int i=n;i>=1;i--){s[i]=t[i];if(s[i+1]<s[i])s[i]=s[i+1];}for(int i=1;i<n;i++){for(int j=i+1;j<n;j++){if(t[i]<t[j] && s[j+1]<t[i]){e[i][j]=e[j][i]=1; //按規則創建圖}}}for(int i=1;i<=n;i++){ if(!color[i]){ //染色paint(i,1);}} }void work(){if(flag==false){printf("0\n");return ; }stack<int> stack1,stack2;int now=1;for(int i=1;i<=n;i++){if(color[i]==1){ //入棧stack1.push(t[i]);printf("a "); }else {stack2.push(t[i]);printf("c "); }while((!stack1.empty() && stack1.top()==now) || (!stack2.empty() && stack2.top()==now)){ //判斷是否彈出if(!stack1.empty() && stack1.top()==now){stack1.pop();now++;printf("b ");}else{stack2.pop();now++;printf("d "); }}} }int main(){flag=1;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&t[i]);}make();work(); return 0; }總結
以上是生活随笔為你收集整理的【每日一题】8月7日题目精讲—双栈排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黄河远上白云间全诗 黄河远上白云间全诗解
- 下一篇: cout,cerr和clog的区别