• AcWing 153. 双栈排序 震惊 !2^n 过 1000


    感觉有点标题党,不过我的代码确实过了qwq。

    题目描述

    可见: https://www.acwing.com/problem/content/155/

    样例

    Input:

    4
    1 3 2 4
    

    Output:

    a b a a b b a b
    

    算法:暴力100pts

    当然还是需要一点剪枝的呀,QAQ.
    我们可以从题目中提取出以下几条性质:

    • 每个栈内上面的数字必须比他小。
    • 要等到当前数字是待输入序列和栈内元素的最小才能弹出。(这个可以用堆)
    • 优先放栈1。(为保证字典序最小)

    思路: (以下用s1表示stack1,s2表示stack2)

    • s1 能放 等价于 s1.empty()||s1.top()>a[u];
    • s1 同理
    • 如果两个栈都不能放,return false;
    • 如果 s1 能放并且 s2 不能放,别无选择,放 s1.
    • 如果 s2 能放并且 s1 不能放,别无选择,放 s2.
    • 如果 s1,s2 都能放,注意了,不是只放 s1 而不放 s2 了,
      因为如果 s1.top() 更大一些,或者其他一些情况,会导致可能不可达,但放 s2 也许就可达了。

    这样直接写肯定不行,所以我们需要一些剪枝(对于s1s2 都能放的情况)。

    1. 如果 s1 是空的,并且 s2 也是,那么放两个栈都是一样的,若 s1 不行,s2 也肯定不行,故只放 s1.
    2. 如果 s1 是空的,并且 s2 不是,没有优化,只能两个都试。
    3. 如果 s1 不是空的,并且 s2 是空的,只放 s1 ,(因为放 s1 的方案都能包容 s2 的,并且字典序更小)。
    4. 如果 s1 不是空的,并且 s2 不是空的
      • s1.top()<s2.top() , 只放 s1,证明同3.
      • s1.top()>s2.top(),没有优化,只能两个都试。

    至此我们可以写出代码。

    Code:

    #include<set>
    #include<map>
    #include<cmath>
    #include<ctime>
    #include<stack>
    #include<queue>
    #include<bitset>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=1e4+5;
    char path[N];
    int n;
    int a[N];
    int tot=0;
    int s1[N],s2[N],t1,t2;
    
    priority_queue<int,vector<int>,greater<int> > q;
    
    bool dfs(int u);
    
    inline bool c1(int u)
    {
    	vector<int> v1,v2;
    	s1[++t1]=a[u];
    	path[++tot]='a';
    	while(s2[t2]==q.top()||s1[t1]==q.top()) {
    		if(s2[t2]==q.top()) {
    			v2.push_back(s2[t2]);
    			q.pop();
    			t2--;
    			path[++tot]='d';
    		}
    		else {
    			v1.push_back(s1[t1]);
    			q.pop();
    			t1--;
    			path[++tot]='b';
    		}
    	}
    	if(dfs(u+1)) return true;
    	if(v1.size()||v2.size()) {
    		while(v1.size()) s1[++t1]=v1.back(),q.push(v1.back()),v1.pop_back(),tot--;
    		while(v2.size()) s2[++t2]=v2.back(),q.push(v2.back()),v2.pop_back(),tot--;
    	}
    	tot--;
    	t1--;
    	return false;
    }
    inline bool c2(int u)
    {
    	vector<int> v1,v2;
    	s2[++t2]=a[u];
    	path[++tot]='c';
    	while(s2[t2]==q.top()||s1[t1]==q.top()) {
    		if(s2[t2]==q.top()) {
    			v2.push_back(s2[t2]);
    			q.pop();
    			t2--;
    			path[++tot]='d';
    		}
    		else {
    			v1.push_back(s1[t1]);
    			q.pop();
    			t1--;
    			path[++tot]='b';
    		}
    	}
    	if(dfs(u+1)) return true;
    	if(v1.size()||v2.size()) {
    		while(v1.size()) s1[++t1]=v1.back(),q.push(v1.back()),v1.pop_back(),tot--;
    		while(v2.size()) s2[++t2]=v2.back(),q.push(v2.back()),v2.pop_back(),tot--;
    	}
    	tot--;
    	t2--;
    	return false;
    }
    
    bool dfs(int u)
    {
    	if(u==n+1) return true;
    	int k1=(t1==0||a[u]<s1[t1]),k2=(t2==0||(a[u]<s2[t2]));
    	if(!k1&&!k2) return false;
    	else if((k1&&!k2)||(k1&&t2==0)||(t1>0&&t2>0&&s1[t1]<s2[t2]&&k1)) {
    		if(c1(u)) return true;
    	}
    	else if(k2&&!k1) {
    		if(c2(u)) return true;
    	}
    	else {
    		if(c1(u)) return true;
    		if(c2(u)) return true;
    	}
    //	if(k1&&c1(u)) return true;
    //	if(k2&&c2(u)) return true;
    	return false;
    }
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	int i;
    	scanf("%d",&n);
    	for(i=1;i<=n;i++) 
    		scanf("%d",&a[i]),q.push(i);
    	if(!dfs(1)) printf("0
    ");
    	else {
    		for(i=1;i<=tot;i++) 
    			printf("%c ",path[i]);
    		printf("
    ");
    	}
    	return 0;
    }
    

    时间复杂度

    最坏情况下是 (O(2^n))
    但也能通过本题。

    启发

    Never give up!.

  • 相关阅读:
    在windows系统下,配置vue项目一键启动文件
    CSS中设置元素的圆角矩形
    CSS中使用文本阴影与元素阴影
    如何使用CSS3中的结构伪类选择器和伪元素选择器
    CSS中的z-index属性如何使用
    深入学习CSS中如何使用定位
    css中如何使用border属性与display属性
    深入了解CSS中盒子模型
    CSS中如果实现元素浮动和清除浮动,看这篇文章就足够了
    CSS标准文档流
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14054169.html
Copyright © 2020-2023  润新知