生成组合对象的算法

发布于 2025-01-07 11:05:53 字数 484 浏览 1 评论 0原文

我正在开发一个时间表生成项目,需要在将数据放入 LP 模型之前对其进行预处理。

我需要生成组合对象以用于优化。该问题与木材切割问题非常相似。

假设我有 3 个班级 {A,B,C} 和 2 个教室,我将采用以下模式:

A
AA
B
BB
C
CC
AB
AC
BC

如果我有 2 个班级 {A,B} 和 3 个教室,我将采用以下模式:

A
AA
AAA
B
BB
BBB
AB
ABB
AAB

3 个班级,3 个房间会给出:

A, B, C,
AA, AB, AC, BB, BC, CC,
AAA, AAB, AAC, ABB, ABC,
ACC, BBB, BBC, BCC, CCC

我需要一个有效的算法来生成这些模式。我的实际数字更像是 5 个以上的教室和 30 个以上的班级,但算法也应该能够处理更大的数字。

I'm working on a timetable generation project and I need to pre-process the data before putting it into an LP model.

I need to generate combinatorial objects to use in optimisation. The problem is very similar to the wood cutting problem.

Say my I have 3 classes {A,B,C} and 2 classrooms, I would have the following patterns:

A
AA
B
BB
C
CC
AB
AC
BC

If I had 2 classes {A, B} and 3 classrooms, I would have the following patterns:

A
AA
AAA
B
BB
BBB
AB
ABB
AAB

3 classes in 3 rooms would give:

A, B, C,
AA, AB, AC, BB, BC, CC,
AAA, AAB, AAC, ABB, ABC,
ACC, BBB, BBC, BCC, CCC

I need an efficient algorithm which generates these patterns. My actual numbers are more like 5+ classrooms and 30+ classes, but the algorithm should be able to handle much larger numbers also.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云归处 2025-01-14 11:05:54

如果你使用 python 那么你可以使用类似的东西:

import itertools
import pprint

def f(classes,classrooms):
    print classes,classrooms
    classes="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[:classes]
    for i in range(1,classrooms+1):
        combinations=itertools.combinations_with_replacement(classes,i)
        pprint.pprint(["".join(j) for j in combinations])

f(3,2)

f(2,3)

f(3,3)

>>>
3 2
['A', 'B', 'C']
['AA', 'AB', 'AC', 'BB', 'BC', 'CC']
2 3
['A', 'B']
['AA', 'AB', 'BB']
['AAA', 'AAB', 'ABB', 'BBB']
3 3
['A', 'B', 'C']
['AA', 'AB', 'AC', 'BB', 'BC', 'CC']
['AAA', 'AAB', 'AAC', 'ABB', 'ABC', 'ACC', 'BBB', 'BBC', 'BCC', 'CCC']
>>>

if you're using python then you could use something like:

import itertools
import pprint

def f(classes,classrooms):
    print classes,classrooms
    classes="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[:classes]
    for i in range(1,classrooms+1):
        combinations=itertools.combinations_with_replacement(classes,i)
        pprint.pprint(["".join(j) for j in combinations])

f(3,2)

f(2,3)

f(3,3)

>>>
3 2
['A', 'B', 'C']
['AA', 'AB', 'AC', 'BB', 'BC', 'CC']
2 3
['A', 'B']
['AA', 'AB', 'BB']
['AAA', 'AAB', 'ABB', 'BBB']
3 3
['A', 'B', 'C']
['AA', 'AB', 'AC', 'BB', 'BC', 'CC']
['AAA', 'AAB', 'AAC', 'ABB', 'ABC', 'ACC', 'BBB', 'BBC', 'BCC', 'CCC']
>>>
伤痕我心 2025-01-14 11:05:53

这是递归策略发挥作用的完美示例。就效率而言,无论您最终使用哪种算法,都可能会出现组合的阶乘爆炸,因此,无论算法的效率如何,使用任何算法,您都将很快以较大的输入实现较长的运行时间。

类似 C# 的语法中的基本算法如下所示:

void GenerateCombinations(string comboSoFar, string classLetters, int level, int maxLevel)
{
    foreach (char letter in classLetters)
    {
        comboSoFar = comboSoFar + letter.ToString();
        Console.WriteLine(comboSoFar);
        if (level < maxLevel)
            GenerateCombinations(comboSoFar, classLetters, level + 1, maxLevel)
    }
}

并以以下基线启动递归函数:

GenerateCombinations("", "ABCD", 1, numberOfClassrooms)

我还没有机会测试任何此代码,因此可能需要一些调整。如果您需要严格的效率,请转换为非递归样式 - 然而,相对较低的性能增益可能不会对您当前的需求产生影响。

This is a perfect example of where a recursive strategy works well. As far as efficiency goes, no matter what algorithm you end up with you could have factorial explosion of combinations, so with any algorithm you'll quickly approach long running times with larger inputs, no matter how efficient the algorithm is.

The basic algorithm in C#-like syntax looks like:

void GenerateCombinations(string comboSoFar, string classLetters, int level, int maxLevel)
{
    foreach (char letter in classLetters)
    {
        comboSoFar = comboSoFar + letter.ToString();
        Console.WriteLine(comboSoFar);
        if (level < maxLevel)
            GenerateCombinations(comboSoFar, classLetters, level + 1, maxLevel)
    }
}

And kick off the recursive function with your baseline of:

GenerateCombinations("", "ABCD", 1, numberOfClassrooms)

I haven't had a chance to test any of this code, so it may need some tweakage. If you need serious efficiency, convert to a non-recursive style -- however chances are the relatively low order of the performance gain won't have an effect on your current requirements.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文