组合数学:10个号楼组100元,而元件保持整理(Combinatorics: Building 10

2019-08-03 03:28发布

我有关于组合数学问题。 不幸的是,我不能抽象地,所以我试图解释它作为一个故事,描述它。 :)

问题:

  1. 有在校园100名儿童。
  2. 它们都具有独特的高度,假设值是100-199cm。
  3. 你想建立10组,每组1-99的儿童。
  4. 你怎么能建立所有的组,而儿童必须由自己的身高进行排序?
  5. 我需要为这些群体所有可能的解决方案,因为它不是很难找到一个星座。

短而简单:

所有的100名儿童并肩而立。 你只需要决定在哪里他们分成不同的小组发现这一切的解决方案。

实施例(的值是高度):

[120 ... 190 ... 199] ... [126 ... 137 ... 144 ... 188] 是不可能

[101] ... [104 ... 105 ... 112 ... 149] ... [169 ... 189] 是可能

我希望你能帮助我。 非常感谢你提前!

PS:这是没有的功课。 ;)通常情况下,我需要一个函数,这是否与数字。 但我无法描述这种抽象,如“门牌的K组,而所有数字进行排序”。 我以为你不会明白这种方式。 :)在PHP中的解决方案是最好的,但我会很高兴地看到其他语言的解决方案,以及。 :)

Answer 1:

据我所知,您实际上要求分割区间[100199]到10份的方式,也就是你想找到数x [0],...,X [10]这样的:

x[0] = 100 < x[1] < x[2] < ... < x[9] < x[10] = 199

定义递归函数partition(intervalSize, pieces)进行计数的方法来分割给定的时间间隔的数目。 您是后partition(100, 10)

下面的Java代码计算分区(对不起,不知道PHP那么好):

public class Partitions
{
    static long[][] partitions = new long[100][10];

    private static long partition(int intervalSize, int pieces)
    {
        if (partitions[intervalSize-1][pieces-1] != 0) {
            return partitions[intervalSize-1][pieces-1];
        }
        long partition = 0L;
        if (pieces == 1) {
            partition = 1L;
        } else {
            for (int i = 1; i <= intervalSize - 1; i++) {
                partition += partition(intervalSize - i, pieces - 1);
            }
        }
        partitions[intervalSize-1][pieces-1] = partition;
        return partition;
    }

    public static void main(String[] args)
    {
        System.out.println(partition(100, 10));     
    }

}

下面的Java代码打印出实际的分区。 由于分区数量为(100,10)那么高,我出的答案(5,3):

public class Partitions2
{
    private static void showPartitions(int sizeSet, int numPartitions)
    {
        showPartitions("", 0, sizeSet, numPartitions);
    }

    private static void showPartitions(String prefix, int start, int finish,
            int numLeft)
    {
        if (numLeft == 0 && start == finish) {
            System.out.println(prefix);
        } else {
            prefix += "|";
            for (int i = start + 1; i <= finish; i++) {
                prefix += i + ",";
                showPartitions(prefix, i, finish, numLeft - 1);
            }
        }
    }

    public static void main(String[] args)
    {
        showPartitions(5, 3);
    }
}

输出是:

|1,|2,|3,4,5,
|1,|2,3,|4,5,
|1,|2,3,4,|5,
|1,2,|3,|4,5,
|1,2,|3,4,|5,
|1,2,3,|4,|5,


Answer 2:

我需要为这些群体所有可能的解决方案,因为它不是很难找到一个星座。

通常情况下,100! 方式来置换100个项目,但因为你是维持秩序,就可以大大减少你的问题的规模了。 什么你所描述的是一个整数分割问题 。 例如,假设你在分区数目5进入所有可能的整数的子集,其新增多达5个,你会得到的集{5},{4,1},{3,2},{3,1,1 ,},{2,2,1},{2,1,1,1},{1,1,1,1,1}。

整数分区的数量与整数的大小呈指数增长,但指数增长足够慢,你可以通过N = 100的所有分区枚举,因为只有他们190569292的。 这里的附加约束条件是要过滤所有的分区的整整含10项,这是很容易通过使用费雷尔图枚举集。

我可以证明由分区的数目20费雷尔图分为3桶:开始用20山口×3行格如下:

 12345678901234567890
1******************
2*
3*

所以,第一个分区是{18,1,1}

现在从堆栈到下一槽的顶部移动的项目:

 12345678901234567890
1*****************
2**
3*

我们的新的分区是{17,2,1}。 我们可以从一个堆栈到其它另一个项目:

 12345678901234567890
1****************
2***
3*

现在我们有{16,3,1}。 你继续这样做,直到你枚举所有排列(它取决于你是否{17,1,2}是从不同的分区{17,2,1})。

从这一点来说,你应该能够想象你所需要的算法的大致轮廓 - 也就是说,如果你想从头开始编写此功能的挑战。 其他人已经写了很多的高效功能轻松解决这个问题。



文章来源: Combinatorics: Building 10 groups of 100 elements while elements remain sorted