题目描述
从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
输入格式
输入一个整数n。
输出格式
每行输出一种方案。
同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。
对于没有选任何数的方案,输出空行。
本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。
1≤n≤15
样例
输入样例:
3
输出样例:
3
2
2 3
1
1 3
1 2
1 2 3
算法1
(采用位运算来模拟) $(2^n)$
一共有n个数字,采用一个n位的二进制数字,如果这一位是1则输出这一位,否则不输出这一位,首现采用一个数字预处理好(2^n->n)的一个映射,采用lowbit,每一次找到最低位的1,然后输出映射的下标
时间复杂度
参考文献
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n;
int h[1<<N];
int lowbit(int x)
{
return x&(-x);
}
int main()
{
cin>>n;
for(int i=0;i<=18;i++)h[1 << i]=i;
for(int i=0;i<(1<<n);i++)
{
int j=i;
for(;j>0;j-=lowbit(j))
{
cout<<h[lowbit(j)]+1<<' ';
}
cout<<endl;
}
return 0;
}
算法2
(暴力枚举) $O(2^n)$
深度优先遍历
时间复杂度
参考文献
C++ 代码
#include<bits/stdc++.h>
using namespace std;
vector<int>choose;
int n;
void cal(int x)
{
if(x==n+1)
{
for(auto u:choose)cout<<u<<' ';
cout<<endl;
return ;
}
cal(x+1);//不选择当前这个数字
choose.push_back(x);//选择当前这个数字
cal(x+1);//选择当前这个数字后得到的一个问题的子状态
choose.pop_back();//回溯到原来的状态
}
int main()
{
cin>>n;
cal(1);
return 0;
}