方法一: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 }