题意
有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;
}