CH1101 火車進棧(爆搜)||(列舉+判斷)
阿新 • • 發佈:2018-12-27
題意
有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; }