双栈排序(codevs 1170)题解
【问题描述】
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希望知道其中字典序最小的操作序列是什么。
【样例输入1】
4
1 3 2 4
【样例输出1】
a b a a b b a b
【样例输入2】
4
2 3 4 1
【样例输出2】
0
【样例输入3】
3
2 3 1
【样例输出3】
a c a b b d
【解题思路】
本题为NOIP2008提高组第四题,初看觉得这应该是有史以来最水的提高组最后一题了,这不是模拟吗?只不过模拟的东西多了一点而已,然而,当我写着写着,就发现模拟的有点不对劲了……
好吧,这道题的正解应该是图的染色+模拟……
是的,没错,你没有看错,第四题居然要模拟!!!
染色其实是一个深搜的过程,染色是为了区分程序从头到尾始终不能放在一个栈中的数,然后为了保证是字典序最小,因此尽量往栈1中放,如果有始终无法放到同一个栈中的数被放到了同一个栈(这里的被放到同一个栈是指的染成同一种颜色),那么就无解,输出0。(染色的方法可以百度floodfill或者种子染色法)
那么问题来了……挖掘机哪家……不对……怎么区分始终不能放在一个栈中的数呢?
如果存在k使得i<j<k且ak<ai<aj则ai和aj不能进入同一个栈。
我们可以手推一下,如果k>j>i说明,j在i的后面进栈,k在j的后面进栈,而此时ai<aj,那么如果ai和aj进了同一个栈,那么就会是aj先出栈,就肯定不是从小到大排好序的了。
染完色后就好办了,直接模拟进栈出栈的过程……如果是最小值,就出,否则就进,然后因为已经染了色了,根据染的色判断它是进(出)栈1还是栈2,然后输出相应的字符即可。
现在还有一个最最担心的问题,怎么确定这个数是不是当前需要出栈的数(即最小值)?好吧……其实是我眼睛瞎了,是的,我为此纠结了半天,然后看题目……一个1~n的排列P……直接最小值赋值为1,然后出栈了就Inc……
【代码实现】
uses math;
var flag:array[..,..] of boolean;
q1,q2,color,a,f:array[..] of longint;
n,i,j,sum,t1,t2:longint;
procedure dfs(x,c:longint);
var i:longint;
begin
color[x]:=c;
for i:= to n do
if flag[x,i] then
begin
if color[i]=c then
begin
writeln();
halt;
end;
if color[i]= then
dfs(i,-c);
end;
end;
begin
readln(n);
for i:= to n do
read(a[i]);
f[n+]:=maxlongint;
for i:=n downto do
f[i]:=min(a[i],f[i+]);
for i:= to n- do
for j:=i+ to n do
if (a[i]<a[j])and(f[j+]<a[i]) then
begin
flag[i,j]:=true;
flag[j,i]:=true;
end;//初始化,哪些是始终无法进同一个栈的
for i:= to n do
if color[i]= then
dfs(i,);//给每一个数染色
sum:=;
for i:= to n do
begin
if color[i]= then
begin
inc(t1);
q1[t1]:=a[i];
write('a ');
end
else
begin
inc(t2);
q2[t2]:=a[i];
write('c ');
end;
while ((t1<>)and(q1[t1]=sum))or((t2<>)and(q2[t2]=sum)) do
begin
if (<>t1)and(q1[t1]=sum) then
begin
dec(t1);
write('b ');
end
else
begin
dec(t2);
write('d ');
end;
inc(sum);//最小值
end;
end;//最恶心的模拟……
end.
双栈排序(codevs 1170)题解的更多相关文章
- 双栈排序(codevs 1170)
题目描述 Description Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈 ...
- [题解] [NOIP2008] 双栈排序——关系的冲突至图论解法
Problem 题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操 ...
- 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)
虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...
- 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)
洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...
- noip2008 双栈排序
题目描述 Description \(Tom\)最近在研究一个有趣的排序问题.如图所示,通过\(2\)个栈\(S_1\)和\(S_2\),\(Tom\)希望借助以下\(4\)种操作实现将输入序列升序排 ...
- #include <NOIP2008 Junior> 双栈排序 ——using namespace wxl;
题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...
- 【NOIP2008】双栈排序
感觉看了题解还是挺简单的,不知道当年chty同学为什么被卡了呢么久--所以说我还是看题解了 原题: Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将 ...
- Noip2008双栈排序
[问题描述] 用两个栈使一个1...n的排列变得有序.一共有四个操作: A.stack1.push() 读入一个放入栈一 B.stack1.pop() 弹出栈一放入输出序列 C.stack2.push ...
- 二分图 and code1170 双栈排序
6.6二分图 二分图是这样一个图: 有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接. 无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶 ...
随机推荐
- SQL执行的原理以及一些常见的关键字
sql语句在面试里面问道的问题: sql的解析的顺序 1.where里面的条件是从右向左扫描解析 2.from里面的大表在前,小表在后,解析的顺序是从右向左解析. 3.left/right/inner ...
- js 未结束的字符串常量错误解决方法
1.JAVASCRIPT引用时,使用的字符语言不一致. 比如:<script type=”text/javascript” src=”xxx.js” charset=”UTF-8″>.xx ...
- unknown software exception
打开cmd 输入下面代码,回车,等跑完即解决for %1 in (%windir%\system32\*.dll) do regsvr32.exe /s %1
- 求编译器中数的最值(c++)
#include <limits> //头文件 #include <iostream> using namespace std; int main() { cout <& ...
- redis错误总结
1.同步错误.不停重试一直不成功 Full resync from master: e51165e2868c541e28134a287f9bfe36372bae34:80575961684 MASTE ...
- 学习练习 java练习小题题目:判断一个整数能被几个9整除
题目:判断一个整数能被几个9整除 package com.hanqi.lianxi; import java.io.*; public class Test1 { //判断能否被9整除 static ...
- 二模08day2解题报告
T1.引爆炸弹(bomb) N个炸弹构成一棵树,引爆一颗叶节点,会一直引爆到根节点.每颗炸弹有一个价值,求引爆k个炸弹的最大价值. 既然是一棵树,那么自然想到dp.所以先树形dp了一遍(由于可能出现多 ...
- oracle权限
Oracle 权限 权限允许用户访问属于其它用户的对象或执行程序,ORACLE系统提供三种权限:Object 对象级.System 系统级.Role 角色级.这些权限可以授予给用户.特殊用户publi ...
- jquery的end(),addBack()方法example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 理解python可变类型vs不可变类型,深拷贝vs浅拷贝
核心提示: 可变类型 Vs 不可变类型 可变类型(mutable):列表,字典 不可变类型(unmutable):数字,字符串,元组 这里的可变不可变,是指内存中的那块内容(value)是否可以被改变 ...