1_1:AcWing 93. 递归实现组合型枚举(dfs)
从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。
输入格式
两个整数 n,m ,在同一行用空格隔开。
输出格式
按照从小到大的顺序输出所有方案,每行 1 个。
首先,同一行内的数升序排列,相邻两个数用一个空格隔开。
其次,对于两个不同的行,对应下标的数一一比较,字典序较小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。
数据范围
n>0 ,
0≤m≤n ,
n+(n−m)≤25
输入样例:
5 3
输出样例:
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
思考题:如果要求使用非递归方法,该怎么做呢?
解析:为了得到一个字典序,只需要从最小的1为根开始往下面搜索即可
#include <iostream> #include <vector> using namespace std; const int N = 30; int n, m; bool st[N]; vector<int>ans; void dfs(int u) { if(ans.size() == m) { for (auto p : ans) cout << p << ' '; cout << endl; return ; } for (int i = u; i <= n; i ++ ) { if(!st[i]) { st[i] = true; ans.push_back(i); dfs(i); ans.pop_back(); st[i] = false; } } } int main() { cin >> n >> m; dfs(1); return 0; }
1_2:AcWing 129. 火车进栈(dfs + stack)
这里有 n 列火车将要进站再出站,但是,每列火车只有 1 节,那就是车头。
这 n 列火车按 1 到 n 的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
也就是说这个火车站其实就相当于一个栈,每次可以让右侧头火车进栈,或者让栈顶火车出站。
车站示意如图:
出站<—— <——进站 |车| |站| |__|
现在请你按《字典序》输出前 20 种可能的出栈方案。
输入格式
输入一个整数 n,代表火车数量。
输出格式
按照《字典序》输出前 20 种答案,每行一种,不要空格。
数据范围
1≤n≤20
输入样例:
3
输出样例:
123 132 213 231 321
解析:
#include <iostream> #include <vector> #include <stack> using namespace std; int n; vector<int>ans; stack<int>st; int u = 1, cnt = 20; void dfs() { if(!cnt) return ; // 方案最多输出20种 if(ans.size() == n) { cnt --; for (auto x : ans) cout << x; cout << endl; return ; } if(st.size()) // 栈里面不空 { ans.push_back(st.top()); st.pop(); dfs(); st.push(ans.back()); ans.pop_back(); } if(u <= n) { st.push(u); u ++; dfs(); st.pop(); u --; } } int main() { cin >> n; dfs(); return 0; }