zoukankan      html  css  js  c++  java
  • 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!.

  • 相关阅读:
    HDU 1754线段树基本操作,建树,更新,查询
    用第三方下载工具下载官方XCode独立安装包的方法
    解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题
    Cygwin 版本的 Curl 安装,提取,使用笔记
    Android Gradle 引用本地 AAR 的几种方式
    VM虚拟机快照还原效果实现方式
    插入中文错误ERROR 1406 (22001): Data too long for column 'name' at row 1
    mysql初始化默认为空的密码修改
    性能测试学习计划(转)
    context-param和init-param区别
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14054169.html
Copyright © 2011-2022 走看看