生成子集

子集問題:寫出集合{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;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章