【问题标题】:generate a list of combinations/sets of numbers with limited supplies [closed]生成数量有限的组合/数字集列表[关闭]
【发布时间】:2011-07-18 18:17:05
【问题描述】:

假设我有 1 个红球、1 个蓝球、2 个黄球和 3 个绿球,总共 7 个球。

我想从 7 个组中选择 3 个球。我有多少种方法可以做到这一点?

当我手动计数时,我得到了 11 个组合/组。即123 124 133 134 144 233 234 244 334 344 444

生成和显示所有这些组合/集合的有效方法是什么?

注意唯一性适用,所以(yellow, red, yellow) = (yellow, yellow, red)

【问题讨论】:

  • 我闻起来像作业,如果是,请添加作业标签
  • 有35种可能的组合,n!/r!(n-r)!
  • @kd7: 不。例如,你不能选择 3 个红色。
  • 哦,是的,你说得对。

标签: combinations combinatorics


【解决方案1】:

不过,我建议使用生成函数方法。

  • 红球个数可以是:0,1
  • 蓝球个数可以是:0,1
  • 黄球个数可以是:0,1,2
  • 绿球个数可以是:0,1,2,3

因此你想扩展以下多项式

(1 + x) * (1 + x) * (1 + x + x^2) * (1 + x + x^2 + x^3)

并查看x^3 的系数,因为您需要总共3 个球。

这将为您提供多种方法,以及获取系数的方法,从每个带括号的表达式中取一项,将告诉您如何进行组合。这是有效的,因为选择01 红球与分别从第一个术语(1 + x) 中选择1x 相同,同样选择i 绿球意味着选择术语x^i从上个学期开始。然后选择的球的总数是指数的总和。既然你想要3 球,你应该看看这个多项式展开时x^3 的系数:

1 + 4x + 8x^2 + 11x^3 + 11x^4 + 8x^5 + 4x^6 + x^7

因此,给定集合中有11 可能的3 球组合。

要迭代可能性,您可以按顺序从表达式中选择一个术语:

int count = 0;
for (int r=0; r<=1 && r<=3; ++r) {
    for (int b=0; b<=1 && r+b<=3; ++b) {
        for (int y=0; y<=2 && r+b+y<=3 ; ++y) {
            for (int g=0; g<=3 && r+b+y+g==3; ++g) {
                count++;
                printf("   red: %d\n  blue: %d\nyellow: %d\n green: %d",r,b,y,g);
            }
        }
    }
}
return count;

前两个 for 循环中的第二个条件(r&lt;=3r+b&lt;=3)在本示例中是不必要的,但我将其保留以说明如何推广问题。

【讨论】:

  • 1:我想选择 3 个球而不是 7 个球。 2:(黄色,蓝色,黄色)与(蓝色,黄色,黄色)相同
  • 太棒了,谢谢。它很好,结构很好
【解决方案2】:
generate_combinations(a1, a2, a3, a4, c1, c2, c3, c4)
1. if a1 + a2 + a3 + a4 = 3 then print (a1, a2, a3, a4)
2. else then
3.    if c1 > 0 then generate_combinations(a1+1, a2, a3, a4, c1-1, c2, c3, c4)
4.    if c2 > 0 then generate_combinations(a1, a2+1, a3, a4, c1, c2-1, c3, c4)
5.    if c3 > 0 then generate_combinations(a1, a2, a3+1, a4, c1, c2, c3-1, c4)
6.    if c4 > 0 then generate_combinations(a1, a2, a3, a4+1, c1, c2, c3, c4-1)

或者类似的东西。但是,这不会捕获重复项...不过,我想您可以添加更多逻辑来过滤掉它们。也许是后期处理?

一些澄清:这可以通过计算 (1) 手中的球和 (2) 袋子中的球来实现。它确保每种颜色的手+包=原创。用一开始空的手调用它,它会打印出你手中可以有三个球的所有方式。

如果您真的想确保算法只给出唯一的(而不是将其与算法结合使用以从列表中删除重复项),您可以确保不添加任何例如如果您已经添加了任何高阶球(即,如果 a2 > 0 且 a1 = 0,那么您不需要添加任何红球),则将红球添加到您的手上。

【讨论】:

  • 太棒了,动态编程总是有效的
猜你喜欢
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
相关资源
最近更新 更多