zoukankan      html  css  js  c++  java
  • 双栈排序 图论

    题目描述

    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希望知道其中字典序最小的操作序列是什么。

    输入输出格式

    输入格式:

    输入文件twostack.in的第一行是一个整数n。

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

    输出格式:

    输出文件twostack.out共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

    输入输出样例

    输入样例#1:
    【输入样例1】
    4
    1 3 2 4
    【输入样例2】
    4
    2 3 4 1
    【输入样例3】
    3
    2 3 1
    
    
    输出样例#1:
    【输出样例1】
    a b a a b b a b
    【输出样例2】
    0
    【输出样例3】
    a c a b b d

    说明

    30%的数据满足: n<=10

    50%的数据满足: n<=50


    首先我们看到两个栈,想到用二分图来做,然后我们考虑怎么建图,要依据一个神奇的规则,然后我们建好图后就开始染色,最后在输出。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define ll long long
    #define il inline
    #define db double
    #define min(a,b) ((a)>(b)?(b):(a))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define MAX 1045
    using namespace std;
    il int gi()
    {
    	int x=0,y=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    		{
    			if(ch=='-')
    				y=-1;
    			ch=getchar();
    		}
    	while(ch>='0'&&ch<='9')
    		{
    			x=x*10+ch-'0';
    			ch=getchar();
    		}
    	return x*y;
    }
    bool pic[MAX][MAX];//保存二分图的
    int color[MAX];//保存每个点的颜色
    int temp[MAX];//保存每个数的大小 
    int small[MAX];//保存i到n中最小的值(用来判断规则)
    int n;
    bool flag;//判断是否有解
    void dfs(int x,int y)
    {
    	color[x]=y;
    	for(int i=1;i<=n;i++)
    		{
    			//如果一条边连到的两个节点颜色相同,则无法建立二分图
    			if(pic[x][i])
    				{
    					if(color[i]==y)
    						flag=1;
    					//给下个点染成另外一种颜色,只有两种颜色
    					if(!color[i])
    						dfs(i,3-y);
    				}
    		}
    }
    il void init()
    {
    	small[n+1]=2e8;
    	//记录q[k]
    	for(int i=n;i>=1;i--)
    		{
    			small[i]=temp[i];
    			if(small[i+1]<small[i])
    				small[i]=small[i+1];
    		}
    	//判断规则
    	for(int i=1;i<n;i++)
    		for(int j=i+1;j<=n;j++)
    			if(temp[i]<temp[j]&&small[j+1]<temp[i])//temp[j]>temp[i]>temp[k]
    					pic[i][j]=pic[j][i]=1;
    	//二分图染色
    	for(int i=1;i<=n;i++)
    		if(!color[i])
    			dfs(i,1);
    }
    il void work()
    {
    	//无法建图
    	if(flag==1)
    		{
    			printf("0
    ");
    			return;
    		}
    	//两个栈
    	int stack1[MAX];
    	int stack2[MAX];
    	int head1=0,head2=0;
    	//只为了少输出一个空格
    	int count=0;
    	//判断是否要出栈
    	int aim=1;
    	for(int i=1;i<=n;i++)
    		{
    			//入栈
    			if(color[i]==1)
    				{
    					stack1[++head1]=temp[i];
    					printf("a");
    					if(count<n*2)
    						printf(" ");
    				}
    			else
    				{
    					stack2[++head2]=temp[i];
    					printf("c");
    					if(count<n*2)
    						printf(" ");
    				}
    			//出栈
    			while((head1!=0&&stack1[head1]==aim)||(head2!=0&&stack2[head2]==aim))
    				{
    					if(head1!=0&&stack1[head1]==aim)
    						{
    							head1--;
    							count++;
    							aim++;
    							printf("b");
    							if(count<n*2)
    								printf(" ");
    						}
    					else
    						{
    							head2--;
    							count++;
    							aim++;
    							printf("d");
    							if(count<n*2)
    								printf(" ");
    						}
    				}
    		}
    	printf("
    ");
    }
    int main()
    {
    	freopen("双栈排序.in","r",stdin);
    	n=gi();
    	for(int i=1;i<=n;i++)
    		temp[i]=gi();
    	init();
    	work();
    	return 0;
    }
    
    PEACE
  • 相关阅读:
    让我们面向切面吧~大话开篇
    成功人士,默默做的30件事 (46)
    使用javassist框架进行动态的更改Class类
    CSS Tools: Reset CSS
    JAVA生成MD5校验码及算法实现
    如何恢复word默认设置
    java md5 3
    js Arrays
    自己写的java md
    java md5 2
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7501220.html
Copyright © 2011-2022 走看看