要求:

  给定一个集合,枚举所有可能的子集。此处的集合是不包含重复元素的。

Method0: 增量构造法

  思路:每次选取一个元素至集合中,为了避免枚举重复的集合,此处要采用定序技巧 -- 除了第一个元素,每次选取必须要比集合中的前一个元素要大!

  

// A 为原集合;
// B 为子集,每次调用函数即会打印一次
// cur 为子集元素个数
void print_subset0(int *A, int *B, int N, int cur) {
for(int i=0; i<cur; i++) {
printf("%5d", B[i]);
}
printf("\n");
if( cur < N ) {
for( int i=0; i<N; i++ ) {
if( !cur || A[i] > B[cur-1] ) {
B[cur] = A[i];
print_subset0(A, B, N, cur+1);
}
}
}
} int main() {
int Length = 3;
int A[Length] = {1, 3, 2};
printf("Method0:\n");
int B[Length] = {0};
print_subset0(A, B, Length, 0);
printf("\n");
return 0;
}

  采用的是递归调用,但此处不需要return语句,因为当没有元素可用于枚举时,就不会调用函数,也就是不会继续递归。

   此函数输出的子集中是包含空集的,如果不想用空集,则需判断 cur 是否为0,不为0才打印子集

   测试样例的输出结果(包含空集):

    

Method1: 位向量法

  思路:1个容量为N的集合,每个位置0~N-1,对于每个子集,要么被选中,要么没被选中。枚举每一个位置的状态,可得到各种子集。

  

// A 为原集合;
// A 为原集合
// used为当前A中每个位置的元素的状态(选中或未被选中)
// cur代表现在枚举A[cur]的状态
void print_subset1(int *A, int *used, int N, int cur) {
if( cur == N ) {
for(int i=0; i<N; i++) {
if( used[i] ) {
printf("%5d", A[i]);
}
}
printf("\n");
return ;
}
used[cur] = 0;
print_subset1(A, used, N, cur+1);
used[cur] = 1;
print_subset1(A, used, N, cur+1);
} int main() {
int Length = 3;
int A[Length] = {1, 3, 2}; printf("Method1:\n");
int B[Length] = {0};
print_subset1(A, B, Length, 0);
printf("\n"); return 0;
}

  同样是递归枚举,这里需要用return终止递归,终止条件就是cur == N即枚举了一种子集,然后输出  

  此函数的输出是包含空集的,如果不想要空集,则需要判断used函数是否全为0,如果全为0,则不输出

  样例输出(包含空集):

    

Method10: 二进制法

  类似于位向量法,同样也是枚举各个位置的状态,但这次用二进制表示,二进制长度为N,与原集合大小相同。二进制的第 i 位代表原集合中的第 i 位是否被选中,枚举各种情况。集合大小为N,就是2的N次种方式。

  

void print_subset10(int *A, int N, int seq) {
for(int i=0; i<N; i++) {
if( seq & (1<<i) ) {
printf("%5d", A[i]);
}
}
printf("\n");
} int main() {
int Length = 3;
int A[Length] = {1, 3, 2};
printf("Method10:\n");
for(int i=0; i<(1<<Length); i++) {
print_subset10(A, Length, i);
}
printf("\n");
return 0;
}

  这种方式很好写,也很好记,但问题是,因为函数中的形参seq是int型的,所以N最大也就只能32,如果long long,那N也只能最大64,再超过64,就需要用大数或其它表示方式表示了。

   如果不想要空集,可以将main函数中的 i 从1枚举起。

  样例输出结果(包含空集):

    

参考资料: 《算法竞赛入门经典(第2版)》

枚举子集的3种方式 -- C++描述的更多相关文章

  1. Java Enum枚举 遍历判断 四种方式(包括 Lambda 表达式过滤)

    示例代码如下: package com.miracle.luna.lambda; import java.util.Arrays; /** * @Author Miracle Luna * @Date ...

  2. iOS中枚举定义的三种方式

    最简单的方式 typedef enum{ num1 = 0, num2 = 1, num3 = 2 }num; 同时我们还可以使用NS_ENUM的方式定义枚举 typedef NS_ENUM (NSI ...

  3. Java Array数组 遍历 四种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.Arrays; /** * @Author Miracle Luna * @Date ...

  4. Java List集合 遍历 四种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.ArrayList; import java.util.List; /** * @A ...

  5. Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.HashMap; import java.util.Iterator; import ...

  6. ASP.NET Core 四种方式绑定枚举值

    前言 本节我们来讲讲在ASP.NET Core MVC又为我们提供了哪些方便,之前我们探讨过在ASP.NET MVC中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满 ...

  7. verilog描述表决器的两种方式简易分析

    命题:设计一个三变量表决器.真值表如下: 可以写出并简化得出公式:F=AB+BC+AC. 以下是两种算法: 第一种:仅从算法方面描述为:A.B.C的和大于1则输出结果为1,否则为0:源码如下: mod ...

  8. 《JS高程》创建对象的7种方式(完整版)

    一.理解对象 ECMA-262定义对象:无序属性的集合,其属性可以包含基本值.对象或者属性. 我们可以把 ECMAScript 的对象想象成 散列表:无非就是一组 名值对,其中值可以是数据或函数. 创 ...

  9. uva1354 天平难题 【位枚举子集】||【huffman树】

    题目链接:https://vjudge.net/contest/210334#problem/G 转载于:https://blog.csdn.net/todobe/article/details/54 ...

随机推荐

  1. web 开发规范

    好久没整理博文了 啰嗦两句  转载至新浪...... 于在未开启cleartype的情况下,一些中文字体在非偶数字号下的显示效果欠佳,所以一般建议使用12.14.16.18.22px等偶数字号.也就 ...

  2. C++数组与指针

    指向数组元素的指针 一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址.指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中) ...

  3. Android应用开发基础篇(10)-----Menu(菜单)

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/28/2372101.html 一.概述 Menu,简单来理解就是当你按下手机的“menu”键时所 ...

  4. BZOJ 2442: [Usaco2011 Open]修剪草坪( dp )

    dp dp[ i ] 表示第 i 个不选 , 前 i 个的选择合法的最小损失 , dp[ i ] = min( dp[ j ] ) ( max( 0 , i - 1 - k ) <= j < ...

  5. Hadoop 相关问题

    1.MR Job 输入非常多,启动map 非常多,如何提高MapTask 启动速度(附加条件:集群很空闲,资源多多): 参考答案: a.重写调度器算法,降低时间复杂度 b.Out-of-bound h ...

  6. 浏览器 窗口 scrollTop 的兼容性问题

    window.pageYOffset 被所有浏览器支持除了 IE 6, IE 7, IE 8, 不关doctype的事, 注IE9 开始支持此属性. window.scrollY 被Firefox, ...

  7. 手动修改VisualStudio IISExpress的配置

    <VisualStudio> <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> ...

  8. OSG项目经验2<在场景中添加文字面版>

    添加文字版需要用到osg的三个名字空间:                         osgText::Text,这个类用来添加文字和设置文字的一些属性:                     ...

  9. 【零基础学习iOS开发】【01-前言】01-开篇

    本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开发 四.学习iOS开发的目的 五.学习iOS开发的前提 从今天开始,我就开始更新[零基础学习iOS开发]这个专题.不管你是否涉足过I ...

  10. Hello China操作系统STM32移植指南(二)

    移植步骤详解 下面就以MDK 4.72为开发环境,详细说明Hello China内核向STM32的移植过程.MDK 4.72评估版只支持32K代码的编译,这对Hello China的内核来说,裁剪掉一 ...