1、遍历组合数的方法原理

组合数是高中代数的知识,这里我就不废话了。

这里讨论的是如何遍历组合数。举个例子,一个电影院里面,有十个座位和8个客人,到底有多少种坐法?(不考虑客人之间的相互位置。)高中组合数的知识告诉我们答案是C = 10 * 9 / 1 * 2 = 45种。

多少种坐法现在我们知道了,现在我们来考虑另外一个变态一点的问题,能不能把45种坐法都罗列出来。

这里给每个座位都编个号(假设第一个座位编号为0),这样就可以列举一些可能的坐法出来:

0 1  2  3  4  5  6  7  8

0 1  2  3  4  5  6  7  9

0 1  2  3  4  5  6  8  9

0 1  2  3  4  5  7  8  9

0 1  2  3  4  6  7  8  9

............

上面的例子来说,对于一般人来说可能还不是很困难,反正也就是45个而已嘛,一个个数总可以数出来。但如果改变题法,比如,50个座位坐5个客人,这样的组合数就达到百万级了,这样的任务对于人来说就已经很困难。

因为组合数的增长速度近似于是指数级的增长,所以靠人肉眼去数是绝对数不过来的,那靠计算机能否实现呢?当然能。不过这需要用到一些数学上面的小技巧。下面的定理给出了这种遍历方法的数学原理。

定理1 设由n个正整数组成的整数集S里,存在着一个固定长度l的有序数列A {},则由所有满足这种关系的序列所组成的序列集{  },就是S关于l的所有组合。

证明:证明该定理,核心是证明是否所有可能的组合情况都能通过序列A的形式表现出来。

(反证法)假设存在着一种整数组合B不满足A的条件,现设,互换这两个数的位置,仍可以使第k位和第k+1位满足约束关系。但互换这两个位置后,原来的次序大小关系可能会被打破。但因为组成B的数都是正整数,根据自然数的良序关系,通过在B内进行位置的互换,总能找到一个子序列B'使。因此通过对B内的数字进行位置互换,总有一个办法使B满足A的约束条件。这与假设矛盾,命题成立。

简而言之,就是在整数集内任意取l个值,总能取出一个按序递增(减)的数列。这听起来像废话,但结论却很重要。这给出了一个在工程上遍历所有组合情况的思路。

2、算法步骤

  1. 以由小(大)到大(小)的顺序按最小步长依次初始化数组的各个元素。其中数组的第一个元素为数集的最小(大)元素。
  2. 从数组最后一位开始加(减)最小步长
  3. 当最后一位遇到溢出(溢出的阀值由整数集的大小确定)时,向前(向后)进位。
  4. 若前(后)一位也继续溢出时,继续向前(后)进位,直至不再溢出,或已经溢出到最前一位,算法结束。
  5. 输出数组的值,然后继续执行2直至算法结束。

下面证明该算法能遍历所有可能的整数组合。

证明:如果将数组看成是一个n进制数,那么数组的每一位元素就相当于各个数位上的值。因为初始化的时候是以从小到大的顺序排列,且最高位为数集中最小的数字S0。所以初始化时构造出的数值(假设为Xmin)必定是最小的。现在按最小步长增加数组的数值,在数组长度有限和可取数字有限的情况下,必定能取遍(Xmin,Xmax)所有的数字组合。

现假设某个数字组合B不能透过上述算法取得,那么这个数字组合对应的n进制数Vb要么大于Xmax,要么小于Xmin。

先考虑Vb < Xmin的情况,Vb < Xmin,意味着在Vb某个高位上存在着一个整数值v 小于Xmin对应位置的值。我们对数值上的所有位从高到低来进行讨论(因为如果低位数值大,但高位数值小,实际的数值也是比原来小)由于最高位数值已经是最小值,不能再小,所以,只能选择次高位。但次高位除非取最小值S0,否则,无法达到比Xmin小的效果。但一旦取S0,组合B就不再是组合数,与原来的题设矛盾。同样的讨论可以继续进行,对后面各位的讨论会发现,除非取前面相同的数字,否则无法找到另外一个数能使Vb < Xmin。因此Vb 一定不小于Xmin.

再来讨论Vb > Xmax的情况,由于讨论最大值的情况也是相似,可以发现每一位,除非取后面相同的值,否则没法达到Vb > Vmax的效果。

由此,可以明确地知道该算法的确能遍历所有组合数。

3、遍历算法的意义

由于组合数的增长是很可观的,即便计算机硬件技术发展到今天,恐怕也没有哪个程序会去求解所有排列组合情况。遍历算法的意义在于,可以在不需要考虑所有排列组合的情况下,挑出心目中最满意的组合。

还是举上面那个例子,假设每个客人对座位的要求都是挑剔的,如果你是电影院的老板,如果随意给他们编座位,可能马上就收到差评。但是也不可能罗列所有的情况让他们自己去挑。因为50个座位给5个人去挑就已经有差不多几百万种情况。因此可能的方案,是随机挑其中的几种给他们去选。但随机取出来的东西,又不能重复,否则程序就会出现死循环。因此最好的方案,就是把每种情况变成一个数值,通过数值的变化,来实现方案的永不重复。(当然现实生活中,最好的方案,就是由客人自己去挑自己心仪的座位,而不是编好位让他们去选。)

总括而言,遍历算法的意义,在于对一些涉及到排列组合的问题上,能快速寻找到下一个组合情况,并能通过存储组合的数字值来代替存储组合本身,节省计算机资源。

如何遍历组合数?(不是求组合数,含代码)相关推荐

  1. 算法 - 数学 - 组合数 - 隔板法求组合数

    一.求组合数 二.隔板法 隔板法是組合數學的方法,用來處理n個無差別的球放進k個不同的盒子的問題.可一般化為求不定方程的解數,並利用母函數解決問題. 隔板法與插空法的原理一樣. 应用隔板法必须满足3个 ...

  2. c 语言 组合数,C++中求组合数的各种方法总结详解

    [问题]      组合问题 问题描述:找出从自然数1.2.... .n中任取r个数的所有组合.例如n=5,r=3的所有组合为: 1,2,3 1,2,4 1,3,4 2,3,4 1,2,5 1,3,5 ...

  3. [AcWing]885. 求组合数 I(C++实现)求组合数模板题

    [AcWing]885. 求组合数 I(C++实现)求组合数第一种题型模板题 1. 题目 2. 读题(需要重点注意的东西) 3. 解法 4. 可能有帮助的前置习题 5. 所用到的数据结构与算法思想 6 ...

  4. 算法刷题-数论-组合数、快速幂、逆元、递推求组合数、逆元求组合数

    文章目录 acwing885. 求组合数 I(递推:数据范围:2000) acwing875. 快速幂(a的k次方 模 b) acwing876. 快速幂求逆元 acwing886. 求组合数 II( ...

  5. java实现n选m组合数_求组合数m_n

    下面为求取组合数的代码: 1 #include #define MAX 10009 int prime[168]; void print(int *v, int length) { int i = 0 ...

  6. 求组合数(不同类型的组合数C++)

    求组合数有许多种不同的算法,要根据不同的数据量大小选择不同的算法 类型1 给定 n 组询问,每组询问给定两个整数 a,b,请你输出 Cba mod(109+7)的值. 输入格式 第一行包含整数 n. ...

  7. Codeforces Round #361 (Div. 2) E. Mike and Geometry Problem 【逆元求组合数 离散化】

    任意门:http://codeforces.com/contest/689/problem/E E. Mike and Geometry Problem time limit per test 3 s ...

  8. 1100: 求组合数(函数专题)

    1100: 求组合数(函数专题) 时间限制: 1 Sec 内存限制: 128 MB 提交: 6264 解决: 4653 [提交] [状态] [讨论版] [命题人:admin] 题目描述 马上要举办新生 ...

  9. ZZULIOJ 1100: 求组合数(函数专题)

    求组合数(函数专题) 题目描述 马上要举办新生程序设计竞赛了,与以往不同的是,本次比赛以班为单位,为了全面衡量一个班级的整体水平,要求从一个班的m位同学中任选k位同学代表本班参加比赛,问有多少种组合方 ...

最新文章

  1. tensor和模型 保存与加载 PyTorch
  2. Android Splash界面支持用户点击 直接进入主界面
  3. 国家五部委联合发布“AI标准顶层设计”:2021年明确、2023年初步建成
  4. 如何保证MongoDB的安全性?
  5. 技术人生:如何成为一位优秀的程序员
  6. Dockerfile基本结构
  7. iec61850采样协议(9-1、9-2)解析(二)
  8. sas ondemand for academics使用
  9. acl在内核里的位置_Linux 进程在内核眼中是什么样子的?
  10. Linux基础学习导图
  11. python中for循环-python中关于for循环的碎碎念
  12. 【OJ1768】最大子矩阵
  13. MyEclipse提示Errors occurred during the build
  14. 1120 Friend Numbers
  15. 建立一个mysql 文件命令是_使用命令行创建数据库
  16. c语言程序文件夹里没看到prj,求教。如何调用编好的函数。如何使用prj文件
  17. ✨❤️CSDN标题党❤️,创意无极限,那不直接全网站都花的飞起?
  18. Android:SQLite和AlertDialog
  19. 【Arcgis】图层的置顶与置底
  20. 用jQuery访问指定元素的父元素

热门文章

  1. SqlServer2017、2019安装注意事项
  2. 程序员辞职理由_我成为程序员的5大理由
  3. 独家专访高通副总裁Max Welling教授:领会因果关系才能泛化智能
  4. SVM算法原理以及实现
  5. Spring Boot项目邮箱验证码功能的实现(以QQ邮箱为例)
  6. 高频覆铜板具有高技术壁垒,我国部分产品已达到世界先进水平
  7. 遗失声明登报 登报挂失 证件登报
  8. 单片机c语言LONG变量,单片机C语言编程当中定义的变量类型决定了什么
  9. P1648看守 题解
  10. 寻找微信pc端缓存的微信小程序图片资源地址