子集生成简介
给定n个数字,枚举出所有可能的子集
例如给定n=3,枚举出{1,2,3}所有可能的子集
{1}、{2}、{3}、{1,2}、{1,2,3}、{2,3}
增量构造法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <cstdio> const int maxn = 100 + 10; //打印0~n-1的所有子集 //按照递增顺序就行构造子集 防止子集的重复 void GenSubsetIncr(int *arr, int n, int cur){ for(int i = 0; i < cur; i++) printf("%d ", arr[i]); printf("\n"); int s = cur ? arr[cur-1] + 1 : 0; //确定当前元素的最小可能值 for(int i = s; i < n; i++){ arr[cur] = i; GenSubsetIncr(arr, n, cur+1); } } int main(){ int n, arr[maxn]; scanf("%d", &n); GenSubsetIncr(arr, n, 0); return 0; } |
位向量法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// 1~n 的所有子集:位向量法 #include <cstdio> const int maxn = 100 + 10; using namespace std; int bits[maxn];//位向量bits[i] = 1,当且仅当i在子集 A 中 void GenSubsetBit(int n,int cur){ if(cur == n){ for(int i = 0; i < cur; i++) if(bits[i]) printf("%d ",i); printf("\n"); return; } bits[cur] = 1; GenSubsetBit(n,cur + 1); bits[cur] = 0; GenSubsetBit(n,cur + 1); } int main() { int n; scanf("%d", &n); GenSubsetBit(n,0); return 0; } |
二进制法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 0 ~ n-1的所有子集:二进制法枚举0 ~ n-1的所有子集 #include <cstdio> const int maxn = 100 + 10; using namespace std; void GenSubset01(int n,int cur){ //这一步其实就是判断 cur 的二进制的各个位上是不是1,如果是1,就输出对应的那个位置(位置从0开始) for(int i = 0; i < n; i++) if(1 & (cur >> i)) printf("%d ",i); printf("\n"); } int main(int argc, char const** argv) { int n; scanf("%d",&n); for(int i = 0; i < (1 << n); i++) GenSubset01(n,i);//枚举各子集对应的编码 0,1,2...pow(2,n) - 1 return 0; } |