每个整数「选 / 不选」构成一棵深度 n 的满二叉决策树,递归遍历即得全部 2^n 个子集;升序天然成立。
OJ: roj
题目 ID: 3006
难度:入门
标签:递归搜索位运算python
创建: 2026-10-01 09:37
更新: 2026-10-06 10:57
题目描述
给定
思路
把每个数看成选/不选决策,
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 09:38
# update_at: 2026-10-01 09:38
import sys
from collections.abc import Iterator
def schemes(n: int, chosen: int = 0, nxt: int = 1) -> Iterator[list[int]]:
"""递归枚举下标 nxt 选或不选;chosen 第 i-1 位为 1 表示整数 i 已选。"""
if nxt > n:
# 叶子:把位掩码还原成升序序列,没有选中任何数时还原成空列表
yield [i for i in range(1, n + 1) if chosen >> (i - 1) & 1]
return
yield from schemes(n, chosen, nxt + 1) # 不选 nxt
yield from schemes(n, chosen | 1 << (nxt - 1), nxt + 1) # 选 nxt
def solve() -> None:
n = int(sys.stdin.buffer.read()) # 题面只有一个整数 n
print("\n".join(" ".join(map(str, choice)) for choice in schemes(n)))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 10:53
* update_at: 2026-10-06 10:53
*/
#include <cstdio>
using namespace std;
typedef long long ll;
int n;
int chosen[20]; // chosen[i] = 1 表示整数 i 已被选中
// 递归枚举第 u 个数选或不选
void dfs(int u) {
if (u > n) {
// 叶子:按升序输出已选中的数
bool first = true;
for (int i = 1; i <= n; ++i) {
if (chosen[i]) {
if (!first) printf(" ");
printf("%d", i);
first = false;
}
}
printf("\n");
return;
}
// 不选 u
chosen[u] = 0;
dfs(u + 1);
// 选 u
chosen[u] = 1;
dfs(u + 1);
}
int main() {
scanf("%d", &n);
dfs(1);
return 0;
}