递归实现组合型枚举

 方法一:dfs加剪枝

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 30;
 4 int n, m;
 5 int way[N]; //方案
 6 void dfs(int u, int start) { //u表示当前枚举到了哪个位置,start表示可以从哪个数枚举
 7     if (u == m + 1) { //如果已经选好了m个数
 8         for (int i = 1; i <= m; i++) {
 9             cout << way[i] << " ";
10         }
11         cout << endl;
12         return;
13     }
14     //如果正在判断第u个位置,那么已经选了u-1个数
15     //从start到n一共有n-start+1个数
16     //如果把这么多个数都选上还凑不够m个数的话,就不合题意
17     //u-1+n-start+1<m,就剪枝
18     //化简即u+n-start<m
19     if (u + n - start < m) {
20         return;
21     }
22     for (int i = start; i <= n; i++) { //从start开始枚举
23         way[u] = i;
24         dfs(u + 1, i + 1);
25         way[u] = 0; //回溯恢复现场
26     }
27 }
28 int main() {
29     cin >> n >> m;
30     dfs(1, 1); //从第一个位置开始枚举,可选择的数字最小是1
31     return 0;
32 }

方法二:书上提供的做法,在递归实现指数型枚举代码的基础上加上判断条件。

不过这样的话,就需要调整一下选择分支的顺序,先进行选择这个数,后进行不选择这个数

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 vector<int> chosen;
 4 int n, m;
 5 void calc(int x) {
 6     if (chosen.size() > m || chosen.size() + (n - x + 1) < m) {
 7         return;
 8     }
 9     if (x == n + 1) {
10         for (int i = 0; i < chosen.size(); i++) {
11             cout << chosen[i] << " ";
12         }
13         cout << endl;
14         return;
15     }
16     //选x这个数
17     chosen.push_back(x);
18     calc(x + 1);
19     chosen.pop_back(); //回溯还原现场
20     //不选x这个数
21     calc(x + 1);
22 }
23 int main() {
24     cin >> n >> m;
25     calc(1);
26     return 0;
27 }

 

posted @ 2020-10-30 10:51  kyk333  阅读(456)  评论(0)    收藏  举报