CH1101 火车进栈(爆搜)||(枚举+判断)

题意

有n个元素,编号1~n,它们依次进栈,随时可以出栈。请你按《字典序》输出前20种可能的出栈方案。

题解1

爆搜
对于一个数k要进栈,先让栈内的元素考虑出栈,然后再入栈。当出栈数等于n时,输出。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30;

int n;
int top=0,sta[maxn];
int on=0,out[maxn];
int cnt=0;

void dfs(int k)
{
    if(on==n)//出栈数等于n时,输出 
    {
        cnt++;
        for(int i=1;i<=n;i++) printf("%d",out[i]);
        printf("\n");
        if(cnt==20) exit(0);
        return ;
    }
    
    if(top>0)//先让栈内的元素考虑出栈
    {
        int tp=sta[top--];
        out[++on]=tp; 
        dfs(k);
        sta[++top]=tp;
        on--;
    }
    
    if(k<=n)//然后再入栈
    {
        sta[++top]=k;
        dfs(k+1);
        top--;
    }
}

int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

 

题解2

枚举+判断
判断原理:一个序列能是出栈序列,当且仅当较大值出站后,后续的小值依次出栈
全排列枚举即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30;

int n;
int a[maxn];
bool v[maxn];
int cnt=0;

bool check()//判断是否是出栈序列
{
    for(int i=1;i<=n;i++)
    {
        int can_mx=a[i];
        for(int j=i+1;j<=n;j++)
            if(a[j]<a[i])
                if(a[j]>can_mx) return false;
                else can_mx=a[j];
    }
    return true;
}

void dfs(int k)//全排列 
{
    if(k==n+1)
    {
        if(check())
        {
            cnt++;
            for(int i=1;i<=n;i++) printf("%d",a[i]);
            printf("\n");
            if(cnt==20) exit(0);
        }
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!v[i])
        {
            v[i]=true;
            a[k]=i;
            dfs(k+1);
            v[i]=false;
        }
    }
}

int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/A_Bright_CH/article/details/81631309
今日推荐