背景
这里有n列火车将要进站再出站……
但是,每列火车只有1节—那就是车头……
描述
有n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
老师:闭嘴!)
就像这样:
出站<——- <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前20种可能的出栈方案。
输入格式
一个整数 n<=20
输出格式
按照《字典序》输出前20种答案,每行一种,不要空格
样例输入
3
样例输出
123 132 213 231 321
- 题解:
- 暴力递归:
- 如果栈非空,把当前栈顶的数出栈
- 把下一个数进栈
- 暴力递归:
这里需要注意递归的顺序问题,而且我们将每次进入递归函数定义为第x个数进栈,所以操作1不需要将x+1再进行递归,而操作2需要。
代码:
//#include<bits/stdc++.h> #include<algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cassert> #include <cstdio> #include <vector> #include <string> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define P(a,b,c) make_pair(a,make_pair(b,c)) #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,a,n) for (int i=n;i>=a;i--) #define CLR(vis) memset(vis,0,sizeof(vis)) #define MST(vis,pos) memset(vis,pos,sizeof(vis)) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef pair<int,pair<int,int> >pii; typedef long long ll; const ll mod = 1000000007; const int INF = 0x3f3f3f3f; ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; } const int MAXN = 50010; int n,m=0,cnt=0,top=0; int a[21],c[21]; void dfs(int x){//当第x个数入栈时 if(m==20)return ;//题目中要求最多输出20个输出 if(x>n+1)return ;//第n+1次进入时不是终止条件,因为第n+1个数进栈时可能进行输出 if(cnt==n){ rep(i,1,n){ cout<<c[i]; } cout<<endl; m++; } if(top){//把这个条件摆在前面是因为多次尝试后,与前面的终止条件配套的顺序是这样,类似于二分,有配套的写法 int tmp=a[top--]; c[++cnt]=tmp; dfs(x); cnt--; a[++top]=tmp; } a[++top]=x; dfs(x+1); top--; } int main(){ scanf("%d",&n); dfs(1); return 0; }