AcWing 递归实现指数型枚举 dfs

 

预备知识:

  一个元素数量为n的集合的子集个数是2^n.

  证明:有n个元素,每个元素进行一次判断要不要把它选出来加进子集里,这样判断n次,产生了2^n种不同结果。

搜索的顺序:

  从前往后遍历1~n,依次判断每个数是选还是不选。

找到一个就输出一个的代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 int st[20]; //标记每一位有没有被选,0表示还没考虑,1表示选,2表示不选 
 5 void dfs(int u) { //u表示当前在判断第几位 
 6     if (u == n + 1) { //如果已经判断完了 
 7         for (int i = 1; i <= n; i++) {
 8             if (st[i] == 1) {
 9                 cout << i << " ";
10             }
11         }
12         cout  << endl;
13         return;
14     }
15     //不选u 
16     st[u] = 2;
17     dfs(u + 1);
18     st[u] = 0; //回溯恢复现场 
19     //选u
20     st[u] = 1;
21     dfs(u + 1);
22     st[u] = 0; //回溯恢复现场 
23 }
24 int main() {
25     cin >> n;
26     dfs(1); //从下标为0开始搜索 
27     return 0;
28 } 
把答案存下来最后输出的代码:
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 int st[20]; //标记每一位有没有被选,0表示还没考虑,1表示选,2表示不选 
 5 int ways[1 << 15][16]; //最多2^15种方案,每种方案15个数
 6 int cnt; //cnt表示当前方案的数量 
 7 void dfs(int u) { //u表示当前在判断第几位 
 8     if (u == n + 1) { //如果已经判断完了 
 9         for (int i = 1; i <= n; i++) { //记录方案 
10             if (st[i] == 1) {
11                 ways[cnt][i] = i;
12             }
13         }
14         cnt++;
15         return;
16     }
17     //不选u 
18     st[u] = 2;
19     dfs(u + 1);
20     st[u] = 0; //回溯恢复现场 
21     //选u
22     st[u] = 1;
23     dfs(u + 1);
24     st[u] = 0; //回溯恢复现场 
25 }
26 int main() {
27     cin >> n;
28     dfs(1); //从下标为0开始搜索 
29     for (int i = 0; i < cnt; i++) {
30         for (int j = 1; j <= n; j++) {
31             if (ways[i][j]) {
32                 cout << ways[i][j] << " ";
33             }
34         }
35         cout << endl;
36     }
37     return 0;
38 }                                                                                             
posted @ 2020-04-23 12:53  kyk333  阅读(119)  评论(0)    收藏  举报