题目要求
Description
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希望知道其中字典序最小的操作序列是什么。
Input
输入有多组Case,每个Case第一行是一个整数n(n<=1000)。
第二行有n个用空格隔开的正整数,构成一个1~n的排列。
Output
每组Case输出一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。
Sample Input
Copy sample input to clipboard
4
1 3 2 4
4
2 3 4 1
Sample Output
a b a a b b a b
0
思考
代码
// Problem#: 19143
// Submission#: 4809694
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <iostream>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <string>
#define max 1000 + 1
using namespace std;
int input[max];
// the min num after each pos
int inputMin[max];
bool edge[max][max];
// 0 for initial, 1 for s1, 2 for s2
// (3 - color) for calculate the other color
int color[max];
stack<int> s1, s2;
bool isUnable;
void initialize() {
while(!s1.empty()) s1.pop();
while(!s2.empty()) s2.pop();
for (int i = 0; i < max; i++) {
input[i] = color[i] = inputMin[i] = 0;
for (int j = 0; j < max; j++) {
edge[i][j] = false;
}
}
isUnable = false;
}
void calMIN(int size) {
for (int i = size - 1; i >= 0; i--) {
if (i == size - 1)
inputMin[i] = input[i];
else inputMin[i] = min(input[i], inputMin[i + 1]);
}
}
void linkEdge(int size) {
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (input[i] < input[j] && inputMin[j] < input[i]) {
edge[i][j] = edge[j][i] = true;
}
}
}
}
void dfs_dye(int pos, int _color, int size) {
color[pos] = _color;
for (int i = 0; i < size; i++) {
if (edge[pos][i]) {
if (color[i] == _color) {
isUnable = true;
break;
} else if (color[i] == 0){
dfs_dye(i, 3 - _color, size);
}
}
}
}
void dye(int size) {
for (int i = 0; i < size; i++) {
if (color[i] == 0) {
dfs_dye(i, 1, size);
}
}
}
void stackSort(int size) {
if (isUnable) {
cout << "0" << endl;
return;
}
int current = 1;
string s;
for (int i = 0; i < size; i++) {
if (color[i] == 1) {
s1.push(input[i]);
s += "a ";
} else {
s2.push(input[i]);
s += "c ";
}
while ((!s1.empty() && s1.top() == current) ||
(!s2.empty() && s2.top() == current)) {
if (!s1.empty() && s1.top() == current) {
s1.pop();
s += "b ";
} else {
s2.pop();
s += "d ";
}
current++;
}
}
for (int i = 0; i < s.size() - 1; i++) cout << s[i];
cout << endl;
}
int main() {
int n;
while (cin >> n) {
if (n > 0) {
// initialize
initialize();
// read data
for (int i = 0; i < n; i++) cin >> input[i];
// processing
calMIN(n);
linkEdge(n);
dye(n);
stackSort(n);
}
}
return 0;
}