給定一個集合,枚舉所有可能的子集,本節討論的集合中沒有重複元素
7.3.1 增量構造法
第一種思路一次選出一個元素放到集合中
#include<stdio.h>
#include<cstring>
using namespace std;
int A[100];
void print_subset(int n,int* A,int cur){
for(int i=0;i<cur;i++)
printf("%d ",A[i]);
printf("\n");
int s=cur?A[cur-1]+1:0;
for(int i=s;i<n;i++){
A[cur]=i;
print_subset(n,A,cur+1);
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(A,0,sizeof A);
print_subset(n,A,0);
}
return 0;
}
上面的代碼用到了定序的技巧:規定集合A中所有元素的編號從小到大排列
7.3.2 位向量法
構造一個位向量B[i],而不是直接構造子集A本身,其中B[i]=1,當且僅當i在子集A中
#include<stdio.h>
#include<cstring>
using namespace std;
int B[100];
void print_subset(int n,int* B,int cur){
if(cur==n){
for(int i=0;i<cur;i++)
if(B[i])
printf("%d ",i);
printf("\n");
return;
}
B[cur]=1; //選第cur個元素
print_subset(n,B,cur+1);
B[cur]=0;
print_subset(n,B,cur+1);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(B,0,sizeof B);
print_subset(n,B,0);
}
return 0;
}
7.3.3 二進制法
爲了處理方便,最右邊的位總是對應元素0,而不是元素1
#include<stdio.h>
#include<cstring>
using namespace std;
int B[100];
void print_subset(int n,int s){
for(int i=0;i<n;i++)
if(s&(1<<i)) printf("%d ",i);
printf("\n");
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
}
return 0;
}