子集問題:寫出集合{1~n}的所有子集
提示:共2n種 增量構造法
一個集合有幾個子集,即求從該集合中可取出多少組合在有n個元素的集合中即Cn0 +Cn1+ .....Cnn=2n
增量構造法:
#include<iostream>
using namespace std;
int n,a[]={1,2,3,4,5,6,7,8,9,10},temp[10]={0};
//temp是存放子集的數組 cur是當前數組下標 pre是上一個存的數 len是要求的子集個數
void dfs(int temp[],int cur,int pre,int len){
if(cur==len){
for(int i=0;i<cur;i++)printf("%d%c",temp[i],i==cur-1?'\n':' ');
return ;
}
for(int i=0;i<n;i++){
if(a[i]>pre){//子集不能重複 所以要大於上一個的數才能存進去
temp[cur]=a[i];
dfs(temp,cur+1,a[i],len);
}
}
}
int main(){
cin>>n;
cout<<"空集\n";
for(int i=1;i<=n;i++){
dfs(temp,0,0,i);//輸出個數爲i的子集
}
return 0;
}
位向量法:
這個方法的核心思路是這樣:由全集確定其子集只要考慮每個元素的狀態是否存在於該子集中即可。
#include<iostream>
using namespace std;//這個方法效率偏低 因爲只取一個元素也要遍歷完全部
//n是個數 b是集合 cur是當前下標
void bitvector(int n,bool b[],int cur){//最後會輸出全是false的空集
if(cur==n){
for(int i=0;i<n;i++)if(b[i])printf("%d ",i+1);
putchar('\n');
return ;
}
b[cur]=true;//丟進集合
bitvector(n,b,cur+1);
b[cur]=false;//不丟進集合
bitvector(n,b,cur+1);
}
int main(){
bool b[100];
bitvector(4,b,0);
return 0;
}
二進制法:
算法思想
例如求4個元素 4 3 2 1 的子集。
那麼用二進制的1代表每一位是否選中。
十進制 二進制
0 0000 代表空集
1 0001 代表{1}
2 0010 代表{2}
3 0011 代表{1,2}
4 0100 代表{3}
...
15 1110 代表{4,3,2}
16 1111 代表{4,3,2,1}
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int n=4;
for(int i=0;i<(1<<n);i++){//二進制0~1111 因爲1左移n位等價於2^n.子集個數2^n
for(int j=0;j<n;j++){//j是用於左移的位數
if(i&(1<<j))printf("%d ",j+1);//比如i=0110,j=1,1<<j=0010,i&j監測s的哪一位爲1,爲1的話輸出
}
printf("\n");
}
return 0;
}