题目地址:
https://www.acwing.com/problem/content/94/
从 1 ∼ n 1∼n 1∼n这 n n n个整数中随机选取任意多个,输出所有可能的选择方案。
输入格式:
输入一个整数
n
n
n。
输出格式:
每行输出一种方案。同一行内的数必须升序排列,相邻两个数用恰好
1
1
1个空格隔开。对于没有选任何数的方案,输出空行。本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
数据范围:
1
≤
n
≤
15
1≤n≤15
1≤n≤15
可以DFS + 状态压缩。用一个整数的右起第 k k k个二进制位表示数 k + 1 k+1 k+1有没有取过( k k k从 0 0 0开始),从空集开始,尝试构造出所有子集,每层循环枚举当前加哪个数进集合,每个DFS树的节点都代表一个方案。代码如下:
#include <iostream>
using namespace std;
int state, n;
void dfs(int u) {
for (int i = 0; i < n; i++)
if (state >> i & 1)
printf("%d ", i + 1);
puts("");
for (int i = u; i < n; i++) {
state += 1 << i;
dfs(i + 1);
state -= 1 << i;
}
}
int main() {
cin >> n;
dfs(0);
return 0;
}
时间复杂度 O ( n 2 n ) O(n2^n) O(n2n),空间 O ( 1 ) O(1) O(1)。