子集生成
2017-03-25 21:45
274 查看
n 个数的子集,每个数都有两种状态:选或不选,所以共有 2^n 种情况;
子集生成有几种不同情况:
第一种是给定 n,生成 1-n 的所有子集;
第二种是给定集合,生成该集合的所有子集;
下面几种方法都是不重复集;
空
1
1 2
1 2 3
1 3
2
2 3
3
1 2 3
1 2 []
1 [] 3
1 [] []
[] 2 3
[] 2 []
[] [] 3
[] [] []
空
1
1 3
1 3 5
1 5
3
3 5
5
1 3 []
1 [] 5
1 [] []
[] 3 5
[] 3 []
[] [] 5
[] [] []
子集生成有几种不同情况:
第一种是给定 n,生成 1-n 的所有子集;
第二种是给定集合,生成该集合的所有子集;
下面几种方法都是不重复集;
1 到 n 的子集
增量构造法:
先列举 3 的子集,找规律,再写程序;空
1
1 2
1 2 3
1 3
2
2 3
3
// 增量构造法 #include <iostream> #include <cstdio> using namespace std; const int maxn = 10000; int arr[maxn]; void sub_set(int *a, int n, int cur) { for(int i = 1; i < cur; i++) printf("%d ", a[i]); printf("\n"); for(int i = (cur==1) ? 1 : arr[cur-1]+1; i <= n; i++) { arr[cur] = i; sub_set(a, n, cur+1); } } int main() { sub_set(arr, 4, 1); return 0; }
行向量法:
数组保存每个数选中还是不选;1 2 3
1 2 []
1 [] 3
1 [] []
[] 2 3
[] 2 []
[] [] 3
[] [] []
// 行向量法 void sub_set1(int *b, int n, int cur) { if(cur > n) { for(int i = 1; i <= n; i++) if(b[i]) printf("%d ", i); printf("\n"); return ; } b[cur] = 1; sub_set1(b, n, cur+1); b[cur] = 0; sub_set1(b, n, cur+1); }
二进制法:
#include <iostream> #include <cstdio> using namespace std; void sub_set(int n, int s) { for(int i = 0; i < n; i++) if(s &(1 << i)) printf("%d ", i); printf("\n"); } int main() { for(int i = 1; i < (1 << 3); i++) { sub_set(3, i); } return 0; }
给定集合的子集
增量构造法:
如 {1, 3, 5}:空
1
1 3
1 3 5
1 5
3
3 5
5
// 增量构造法 #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 10000; int arr[maxn]; // 仅适用于集合非负,当然可以根据集合重新memset一下 void sub_set(int *a, int *b, int n, int cur) { for(int i = 1; i < cur; i++) printf("%d ", a[i]); printf("\n"); for(int i = cur; (a[cur-1] != b[n-1]) && i <= n; i++) { // 不设置这一步会出现 3 3 的情况,因为后面一个3没有和前面的3一样同步i while(b[i-1] == a[cur-1]) i++; a[cur] = b[i-1]; sub_set(a, b, n, cur+1); } } int main() { memset(arr, -1, sizeof arr); int b[] = {0, 1, 3}; sub_set(arr, b, 3, 1); return 0; }
行向量法:
1 3 51 3 []
1 [] 5
1 [] []
[] 3 5
[] 3 []
[] [] 5
[] [] []
// 行向量法 void sub_set1(int *a, int *b, int n, int cur) { if(cur > n) { for(int i = 1; i <= n; i++) if(b[i]) printf("%d ", a[i-1]); printf("\n"); return ; } b[cur] = 1; sub_set1(a, b, n, cur+1); b[cur] = 0; sub_set1(a, b, n, cur+1); } int main() { int b[4]; int a[] = {1,2,3}; sub_set1(a, b, 3, 1); return 0; }
相关文章推荐
- 子集生成算法
- subsets之给定一个数列&生成该数列所有的子集&升序
- 生成子集
- 暴力求解法--生成子集
- uva 11205 The Broken Pedometer(经典的子集生成题目,在此总结了三种子集生成的方法~)
- 生成子集
- UVA 1151 - Buy or Build(最小生成树,二进制子集生成)
- (子集生成算法)
- 入门经典 第七章 7.3.1 增量构造生成子集
- uva-1151-Buy or Build-二进制枚举子集,并查集,最小生成树,kruskal
- UVA 1151 Buy or Build(最小生成树+枚举子集)
- 2018寒假训练-紫皮书-子集生成
- 【算法竞赛入门经典】7.3子集生成【增量构造法】【位向量法】【二进制法】
- 子集生成算法
- 子集生成的两种方法
- 子集生成
- 位向量法生成子集
- HDU4462(子集生成)
- 子集生成算法
- 排列组合,子集生成问题,与nyoj 组合数