子集生成的三种方法
最近遇到一个子集生成的题 没有很快的写出来 所以在把之前的过的子集生成方法在复习一边
第一种 增量构造法
在lrj紫书中 这是放到第一个讲解的 。。。。。。
顾名思义 增量构造法 就是按照递增顺序就行构造子集 防止子集的重复 如 集合{1,2} 就不会输出{1,2} 和{2,1}这样重复的子集了 在解答书中生成
2^n方个子集
直接看代码吧
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 300
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;//确定当前最小的可能值 如果这里不是 这里特殊的就是cur==0时 其他的就是选比前一个大1的
for(int i=s;i<n;i++)
{
A[cur]=i;//将i加入当前的集合
print_subset(n,A,cur+1);// 递归构造子集
}
}
int main()
{
int n;scanf("%d",&n);
print_subset(n,A,0);
}
第二种 位向量法
这个就不多数了 最简单的 就i是选与不选 代码比较好些 容易理解 但是解答树节点是 2^n+1-1 比上面的大一倍
容易处理他给出的集合
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 300
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;
print_subset(n,B,cur+1);//选
B[cur]=0;
print_subset(n,B,cur+1);//不选
}
int main()
{
int n;scanf("%d",&n);
print_subset(n,B,0);
}
第三种 也是应用最广的一种 这种思想在很多地方都能用到 非常好用 二进制法
简单的说就是二进制的每一位代表一个数
A B A&B A|B A^B
10110 01100 00100 11110 11010
{1,2,4} {2,3} {2} {1,2,3,4} {1,3,4}
可以看出分别对应 交 并 差 全集是 n个1 就是2^n-1 all_set=(1<<n)-1 则A的补集是all_set^A
上代码吧
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 300
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;scanf("%d",&n);
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
}
下面是一些集合的操作
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 300
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;scanf("%d",&n);
for(int i=0;i<(1<<n);i++)
print_subset(n,i);
}
空集 s=0
只含有第i个元素 1<<i
含有全部n个元素 (1<<n)-1
判断第i个元素是否属于集合S S>>i &1
向集合中加入第i个元素 s|=1<<i
从集合中去除元素i s&~(1<<i)
集合S和集合T的并集 S|T
集合S和集合T的交集 S&T