暴力求解法_子集生成(增量构造法,位向量法,二进制法)
2017-08-07 16:04
387 查看
子集生成
子集生成算法:给定一个一级和,枚举它的所有可能的子集。
输入:
4
输出:
增量构造法
第一种思路是一次选出一个元素放到集合中
code:
#include <stdio.h> int A[1010]; void print_subset(int n,int* A,int cur){ int flag=0; for(int i=0;i<cur;i++)//打印当前集合 {printf("%d ",A[i]);flag=1;} if(flag==1) printf("\n"); int s= cur ? A[cur-1]+1:1;//确定当前元素的最小可能值 for(int i=s;i<=n;i++){ A[cur]=i; print_subset(n,A,cur+1); } } int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++)A[i]=i+1; print_subset(n,A,0); return 0; }
输入:
4
输出:
1
1 2
1 2 3
1 2 3 41 2 41 3
1 3 41 42
2 3
2 3 42 43
3 44
位向量法
第二种思路是构造一个位向量B[i],而不是直接构造子集A本身,其中B[i]当且仅 i 在子集A中。
code:
#include <stdio.h> int B[1001]; 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+1); //打印当前集合,注意此时B[i]保存的是子集A是否已经使用的状态 printf("\n"); return; } B[cur]=1;//选择第cur个元素 print_subset(n,B,cur+1); B[cur]=0;//不选择第cur个元素 print_subset(n,B,cur+1); } int main() { int n; scanf("%d",&n); print_subset(n,B,0); return 0; }
输入:
4
输出:
1 2 3 41 2 3
1 2 41 2
1 3 41 3
1 41
2 3 42 3
2 42
3 43
4
二进制法
另外,还可以使用二进制来镖师{0,1,2…,n-1}的子集S:从右往左第 i 为(各位从0开始编号)表示元素i是否在集合S中。1先转成二进制 在左移n位 然后补0
比如 1<<2 ,1的二进制为 0000 0001,左移2位 0000 0100。 如果再转成10进制就是4。
例如:
for(i=0;i<(1<<n);i++)
- n=1,即1*2;
- n=2,即1*2*2;
- n=4,即1*2*2*2*2;转化为二进制10000.
code:
#include <stdio.h> void print_subset(int n,int s){ int flag=0; for(int i=0;i<n;i++) if(s&(1<<i)) {printf("%d ",i+1);flag=1;} if(flag==1) printf("\n"); } int main() { int i,n; scanf("%d",&n); for(i=0;i<(1<<n);i++){//枚举各子集所对应的编码0,1,2...,2^n-1 print_subset(n,i); } return 0; }
相关文章推荐
- 【算法竞赛入门经典】7.3子集生成【增量构造法】【位向量法】【二进制法】
- 子集生成 增量构造法 位向量法 二进制法
- 子集生成的两种方法 (增量构造法 和 位向量法)
- 子集生成算法 之 位向量法和增量构造法
- 子集生成算法——增量构造法
- 子集生成之增量构造法(允许有重复元素)
- 枚举子集 增量构造法 位向量法 二进制法
- [Day 1] 7.3.1 子集生成-增量构造法
- 二进制法生成子集
- ACMjava子集生成的三种方法,增量构造,辅助位向量,二进制法
- [Day 1] 7.3.3 子集生成-二进制法
- 子集生成 -- 二进制法
- 《算法竞赛入门经典》-【第七章:暴力求解法】-7.3:子集生成
- 生成子集——位向量法
- 算法分析与设计-减治法3:生成子集的减治算法及二进制法
- 子集生成(位向量法)
- 增量构造法输出所有子集
- 入门经典 第七章 7.3.1 增量构造生成子集
- 算法竞赛入门经典:第七章 暴力求解法 7.8子集生成
- 二进制法生成子集