子集和问题:一种组合生成算法

今天在网上看见这么一道题目:给你m个数,从里面找出和为sum的n个数,问一共能找到多少组这样的 数。

根据我的理解,这是一道组合生成的题目。令m个数组成的集合为M,就是要找到所有元素个数为n且和 为sum的子集。

最笨的方法是生成所有的子集,然后进行验证,这样复杂度为阶乘。显然有一种改进的算法,在笨方 法中,我们连元素个数不为n的子集都生成了,而这显然是不必要的。这种改进想到很容易,但实现起来 有点困难,经过数个小时的艰苦奋战,我终于设计了一种原创性的组合生成算法,虽然它应该早被计算机 科学家想到了,但我还是抑制不住激动。

我们知道元素个数为m的几何,它的大小为n的子集的个数肯定是C(m,n),由于博客园不能用Tex写公式 ,我只能这样表示组合公式。理想的算法应该是只生成这些子集,这谁都知道,关键是怎么通过一种可列 的方式来生成它们。

我们用一个二进制数来表示集合,用一个二进制位来表示元素,相应位是1则说明集合包含该元素,否 则不包含。先考虑一个特例,集合A的大小为5,生成所有大小为3的子集。显然 00111符合条件,01011也 符合条件,还有01110、01101,但是我们不能瞎猜吧。下面我画出树图,也是我的思维图。

上图就是5选3的结果,现在我们来分析一下怎么由父结点生成子结点,根结点可以很容易求出来,如 果知道如何由父生成子,那么整个问题就解决了。我用序对(p,q)表示将第p位变为1,第q位变为0,注 意下标从0开始。请检查下列序对是否有00111生成了他的5个儿子。

(3,0)
(3,1)
(3,2)
(4,1)
(4,2)

请认真验证上面的操作,有些东西是无法用语言来表达的,相信验证之后你就理解得差不多了。对, 红色的位置是分界线,p从红色的位置开始递增,而q是从0递增到红色位置的前面一位,反映在程序中应 该是个二层循环:外层是p在递增,内层是q在递增。

时间: 2024-11-30 09:41:44

子集和问题:一种组合生成算法的相关文章

退火算法-java最优组合算法问题,编程实现字母最优组合生成最优解

问题描述 java最优组合算法问题,编程实现字母最优组合生成最优解 要求:输入A~K中的任意几个字母(无重复),对这些字母进行组合.输出最优组合的最小组数n和组合方案,使用java语言. 约束条件:A可以和B一组: A可以和E.F.G一组: C.D.H要单独分组: I可以和E.F.G一组: J可以和E.F.G一组: K可以和E.F.G一组: 如果可以,希望用退火算法的思想来解决本问题.毕设赶着要用这个算法,希望尽快提供解决方案,拜谢! 解决方案 两两组合,还是可以多个组合? 解决方案二: 必须是

浅析实现排列组合查询算法

所谓的排列组合查询就相当于GOOGLE高级查询中"包含以下全部的字词"查询,也就是说查询中必须包含所有查询关键词,而且他们的顺序可以是任意.以下程序段实现了这一功能.比如输入查询关键字:tom tina则最一般的情况是在程序中使用类似于"select sex from student where name like '%tom%tina%' or name like '%tina%tom%' ordered by age" 的查询语句实现以上的查询,因此如何得到'%

php四种基础排序算法的运行时间比较

/**  * php四种基础排序算法的运行时间比较  * @authors Jesse (jesse152@163.com)  * @date    2016-08-11 07:12:14  */ //冒泡排序法 function bubbleSort($array){     $temp = 0;     for($i = 0;$i < count($array) -1;$i++){         for($j = 0;$j < count($array) - 1 -$i;$j++){  

技术 | 使用深度学习检测DGA(域名生成算法)

DGA(域名生成算法)是一种利用随机字符来生成C&C域名,从而逃避域名黑名单检测的技术手段.例如,一个由Cryptolocker创建的DGA生成域xeogrhxquuubt.com,如果我们的进程尝试其它建立连接,那么我们的机器就可能感染Cryptolocker勒索病毒.域名黑名单通常用于检测和阻断这些域的连接,但对于不断更新的DGA算法并不奏效.我们的团队也一直在对DGA进行广泛的研究,并在arxiv发表了一篇关于使用深度学习预测域生成算法的文章. 本文我将为大家介绍一种,简单而有效的DGA生

PHP实现四种基础排序算法的运行时间比较(推荐)

许多人都说算法是程序的核心,算法的好坏决定了程序的质量.作为一个初级phper,虽然很少接触到算法方面的东西.但是对于基本的排序算法还是应该掌握的,它是程序开发的必备工具.下面通过本文给大家介绍PHP实现四种基础排序算法的运行时间比较,一起看下吧. 废话不多说了,直接给大家贴代码了. 具体代码如下所示: /** * php四种基础排序算法的运行时间比较 * @authors Jesse (jesse152@163.com) * @date 2016-08-11 07:12:14 */ //冒泡排

.NET平台下带权限控制的TreeView控件节点生成算法

treeview|控件|控制|算法 一.引言 在应用系统开发中,TreeView是一种使用频率很高的控件.它的主要特点是能够比较清晰地实现分类.导航.浏览等功能.因而,它的使用方法与编程技巧也一直受到技术人员的关注.随着应用需求的变化,在很多情况下我们需要实现数据显示的权限控制,即用户看到的数据是经过过滤的,或是连续值,或是一些离散的值.就TreeView而言,原先可能显示出来的是完整的具有严格父子关系得节点集,而经权限过滤后所要显示的节点可能会变得离散,不再有完整的继承关系.本文针对这一问题,

算法系列(十三) 椭圆的生成算法

椭圆和直线.圆一样,是图形学领域中的一种常见图元,椭圆的生成算法(光栅转换算法)也是图 形学软件中最常见的生成算法之一.在平面解析几何中,椭圆的方程可以描述为(x – x0)2 / a2+ (y – y0)2 / b2 = 1,其中(x0, y0)是圆心坐标,a和b是椭圆的长短轴,特别的,当(x0, y0)就是坐标 中心点时,椭圆方程可以简化为x2 / a2 + y2 / b2 = 1.在计算机图形学中,椭圆图形也存在在点阵 输出设备上显示或输出的问题,因此也需要一套光栅扫描转换算法.为了简化,

算法系列(十一) 圆生成算法

在平面解析几何中,圆的方程可以描述为(x – x0)2 + (y – y0)2 = R2,其中(x0, y0)是圆心坐 标,R是圆的半径,特别的,当(x0, y0)就是坐标中心点时,圆方程可以简化为x2 + y2 = R2.在计算 机图形学中,圆和直线一样,也存在在点阵输出设备上显示或输出的问题,因此也需要一套光栅扫描 转换算法.为了简化,我们先考虑圆心在原点的圆的生成,对于中心不是原点的圆,可以通过坐标的 平移变换获得相应位置的圆. 在进行扫描转换之前,需要了解一个圆的特性,就是圆的八分对 成

算法系列(十) 直线生成算法

在欧氏几何空间中,平面方程就是一个三元一次方程,直线就是两个非平行平面的交线,所以直线 方程就是两个三元一次方程组联立.但是在平面解析几何中,直线的方程就简单的多了.平面几何中 直线方程有多种形式,一般式直线方程可用于描述所有直线: Ax+By+C = 0  (A.B不同 时为0) 当知道直线上一点坐标(X0,Y0)和直线的斜率K存在时,可以用点斜式方程: Y-Y0 = K(X – X0) (当K不存在时,直线方程简化成X = X0) 当知道直线上的两个点 (X0,Y0)和(X1,Y1)时,还可