《算法竞赛进阶指南》双栈排序

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>

untitled.png

当然,这样的操作序列有可能有几个,对于上例(1, 3, 2, 4),<a, c, c, b, a, d, d, b>是另外一个可行的操作序列。

Tom希望知道其中字典序最小的操作序列是什么。

输入格式
第一行是一个整数n。

第二行有n个用空格隔开的正整数,构成一个1-n的排列。

输出格式
输出共一行,如果输入的排列不是”可双栈排序排列”,输出数字0。

否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

数据范围
1≤n≤1000
输入样例:
4
1 3 2 4
输出样例:
a b a a b b a b

本题如果我们正向思维思考的话那就是贪心了,我们这里用逆向思维用特定的条件去把所有的元素分配到两个栈中去:

我们首先看一个栈的问题我们举一个简单的例子:2、3、1的话用一个栈是不能排序的,当然1、2、3的其他组合是都可以用一个栈进行排序的,这时我们就从元素大小和位置的角度出发就有一个推论:

当i<j<k并且a[i]<a[j],a[i]>a[k],又因为k位置的元素是还没有放入到当前栈中的,所以改变这种状态的话只能将j位置元素放入到另一个栈中,这里的分配方法用的是二分图染色,优先考虑第一个栈的操作:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
const int N=1010;
int a[N],f[N];
bool g[N][N];
int n;
int color[N];
bool dfs(int u,int c)
{
   //二分图模板
   color[u]=c;//将u位置染色为目标色
   for(int i=1;i<=n;i++)
   	if(g[u][i])//如果i位置和u位置不能染同一个染色的话
   	{
   
       
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值