【图-二分图染色】NOIP提高组2008双栈排序
来源:互联网 发布:java报表管理系统源码 编辑:程序博客网 时间:2024/06/06 21:05
【问题描述】
Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。
操作a
如果输入序列不为空,将第一个元素压入栈S1
操作b
如果栈S1不为空,将S1栈顶元素弹出至输出序列
操作c
如果输入序列不为空,将第一个元素压入栈S2
操作d
如果栈S2不为空,将S2栈顶元素弹出至输出序列
Tom希望知道其中字典序最小的操作序列是什么。
【题目分析】
1.暴力解法
维护俩个单调的栈,对于每一个元素,显然可以进行如下操作顺序
优先判断S1里面第一个元素能否能出栈,若能出栈,则当前最优解一定是b操作
然后判断当前元素x是否能进入S1栈,若能则试验a操作(未必最优)
再判断S2里面第一个元素能否能出栈,若能出栈,则当前最优解一定是d操作
最后试验将x放入S2
2.优化:自己手动数据四五次后找到了规律:设输入序列为S,考虑S[i],S[j]两个元素不能进入同一个栈的条件.注意,这里所说的”S[i],S[j]两个元素不能进入同一个栈”,不是说仅仅不能同时在一个栈中,而是自始至终不能进入一个栈,即如果有解,那么S[i],S[j]一定进入过的栈不同.
结论P: S[i],S[j]两个元素不能进入同一个栈 <=> 存在k,满足i < j < k,使得S[k] < S[i] < S[j].
这里注意要对于k的枚举进行预处理
#include <iostream>#include <cstdio>using namespace std;int n,now=1,a[1001],least[1002],color[1001],map[1001][1001]; bool used[1001]; char caozuo[2010]; int q1[1001],q2[1001],top1,top2; bool shutcolor,shut;void read(){ int i; cin>>n; for (i=1;i<=n;i++) cin>>a[i]; least[n]=a[n]; for (i=n-1;i>=1;i--) least[i]=min(least[i+1],a[i]); q1[0]=1001; q2[0]=1002; now=1; top1=1; top2=1; return;}void getcolor(int k,int c){ if (shutcolor) return; if (used[k]) { if (c==color[k]) return; else { shutcolor=1; return; } } used[k]=1; color[k]=c; int i,need; if (c==1) need=2; else need=1; for (i=1;i<=map[k][0];i++) getcolor(map[k][i],need); return;}void getmap(){ int i,j; for (i=1;i<=n;i++) for (j=i+1;j<n;j++) if (a[j]>a[i]) if (least[j+1]<a[i]) { map[i][0]++; map[i][map[i][0]]=j; map[j][0]++; map[j][map[j][0]]=i; } for (i=1;i<=n;i++) if (used[i]==0) getcolor(i,1); return;}void print(){ int i; for (i=1;i<2*n;i++) cout<<caozuo[i]<<" "; cout<<caozuo[2*n]; return;}void work(int k,int u){ if (shut) return; if (u==2*n+1) { shut=1; print(); return; } if (now==q1[top1]) { caozuo[u]='b'; top1--; now++; work(k,u+1); top1++; now--; } else if (color[k]==1) { caozuo[u]='a'; top1++; q1[top1]=a[k]; work(k+1,u+1); top1--; } if (now==q2[top2]) { caozuo[u]='d'; top2--; now++; work(k,u+1); top2++; now--; } else if (color[k]==2) { caozuo[u]='c'; top2++; q2[top2]=a[k]; work(k+1,u+1); top2--; } return;}void judge(){ int i; for (i=1;i<=n;i++) if (color[i]==0) color[i]=1; if (shutcolor==0) work(1,1); else cout<<0; return;}int main(){ freopen("twostack.in","r",stdin); freopen("twostack.out","w",stdout); read(); getmap(); judge(); return 0;}
0 0
- 【图-二分图染色】NOIP提高组2008双栈排序
- 【NOIP2008提高组T4】双栈排序-二分图染色
- NOIP 2008 双栈排序 二分图
- NOIP 2008 双栈排序 (COGS 221) 二分图
- [栈 二分图染色] NOIP2008 双栈排序
- noip2008 双栈排序 (二分图染色)
- C++:二分图染色法---双栈排序
- 洛谷 1155 双栈排序 NOIP2008 图论 二分图染色
- 【NOIP2008】【二分图染色】T4 双栈排序 题解
- 【luogu1155】双栈排序(二分图染色)
- 洛谷OJ 1155 双栈排序(二分图染色)
- 洛谷1155 NOIP2008 双栈排序【二分图染色】
- 洛谷 1155 [NOIP2008] 双栈排序 二分图染色+模拟
- 【图-二分图染色】NOIP2010提高组关押罪犯
- NOIP 2010 关押罪犯 二分答案+二分图染色判定 COGS 520
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
- XJOI NOIP16提高组赛前训练17 T1:GotoAndPlay(二分图染色)
- NOIP 2010 - 提高组 关押罪犯 二分答案+二分图的判定
- 安卓APP开发简单实例 结对编程心得
- HDU1058Humble Numbers
- BestCoder Round #81 (div.2)-String(尺取法)
- 前端笔记 CSS 5
- 学习新技术知识的方法
- 【图-二分图染色】NOIP提高组2008双栈排序
- uploadify上传图片
- 【codevs】基础合集(一)
- Linux下用户组、文件权限详解
- BlogLife
- 读远--下电子书的好地方
- HDU 5670 Machine——BestCoder Round #81(div.2)
- Ruby元编程-学习笔记(二)-方法
- Android ADT 下载代理