--- title: "枚举子集" created: 2025-11-28 tags: - 算法 --- # 枚举子集 ## 题目 [递归实现指数型枚举](https://www.acwing.com/problem/content/94/) ![[image-061d9780.png]] ## 思路分析 每个位置不外乎是选还是不选 这可以联想使用二进制的01来表示状态 可以用二进制枚举子集做二进制枚举子集 二进制的方式虽然更容易理解些 但是效率方面会比较低 历年几个题都是 当时想到了用二进制枚举的方式 但是因为效率过低而暴力不出来 所以这类问题还是选择用dfs求解吧 因为dfs可以剪去一些没用的枝 从而较大地提高效率 适用性也更高 因为有时候每个位能考虑的情况会更多而不只是选与不选两种情况 dfs实质也就是递归 ![[image-d66b317b.png]] ## 代码实现 **81ms** ```cpp #include using namespace std; const int N=16; int st[N];//状态,记录每个位置当前的状态:0表示还没考虑,1表示选它,2表示不选它 int n; void dfs(int u){ if(u>n){ for(int i=1;i<=n;i++) if(st[i]==1) cout<>n; dfs(1); return 0; } ``` 138ms 不再推荐二进制枚举的方式 ```cpp #include using namespace std; // 输出所有可能的选择方案 vector> subsets(int n) { vector> ans; // 从空集开始,到所有元素都选中的集合结束,共2^n种可能 for (int mask = 0; mask < (1 << n); ++mask) { vector t; // 遍历每个元素,看其是否应该包含在当前子集中 for (int i = 0; i < n; ++i) { if (mask & (1 << i)) { // 由于题目中的数是从1开始的,所以这里要加1 t.push_back(i + 1); } } ans.push_back(t); } return ans; } int main() { int n; cin >> n; auto ans = subsets(n); // 输出所有子集,每个子集内的数字按升序排列 for (auto &subset : ans) { for (int num : subset) { cout << num << " "; } cout << endl; } return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[2-Learning/02-算法/03-刷题理模型/递归与递推模型/递归/带分数|带分数]] 🏠 [[00-刷题理模型]] ➡️ [[简单斐波那契(递归实现)|简单斐波那契(递归实现)]]