复杂的排列/组合

时间:2012-06-26 10:18:01

标签: data-structures permutation combinations

摘要:
您选择要注册的模块。
每个模块都有许多组。
每组代表给定模块的讲座。
每个组合应该只包含每个模块中的一个组。

实施例:
COS 121 -3团体
COS 132 -2组

这将为您提供6个选项:[1,1],[1,2],[2,1],[2,2],[3,1],[3,2]

我的观点: 我需要使用每个组合来生成时​​间表,所以我使用一个数组来存储当前正在使用的组和组的总数:arrSubjects[subject,currentGroup,maxGroups]

逻辑上,您应该能够遍历此数组以使用每个组的组合。

我无法掌握这个解决方案,可能是因为我使用了错误的角度。任何帮助/建议都会非常感激。

我目前的实施: 我对此感到很尴尬,因为它花了很多时间,但它确实有效。 这是伪代码的基本内容:

for (all the groups multiplied with eachother) do {
  for (all the modules selected) do {
    Select a random group between 1 and the nmr of groups 
  }
}

之后我必须摆脱所有重复。

提前致谢

我目前正在处理的代码:

arrPermutations[0,0]:=1;//Current group for 1st module
arrPermutations[0,1]:=3;//Max groups for 1st module
arrPermutations[1,0]:=1;
arrPermutations[1,1]:=3;
arrPermutations[2,0]:=1;//Current group for 3rd module
arrPermutations[2,1]:=3;//Max groups for 3rd module
iCurrent:=iMax; //2
while (arrPermutations[0,0]<=arrPermutations[0,1]) do
begin
//Display arrPermutations
if arrPermutations[iCurrent,0]=arrPermutations[iCurrent,1] then
begin
  Inc(arrPermutations[iCurrent-1,0]);
  for i := iCurrent to iMax do
    arrPermutations[i,0]:=1;
  iCurrent:=iMax;
end else
begin
  Inc(arrPermutations[iCurrent,0]);
end;
end;

目前我只是穿越最后两组。 这是检查时得到的输出:
= ============运行1 ==============
模块,当前组,最大组
1,1,3
2,1,3
3,1,3
= ============运行2 ==============
模块,当前组,最大组
1,1,3
2,1,3
3,2,3
= ============运行3 ==============
模块,当前组,最大组
1,1,3
2,1,3
3,3,3
= ============运行4 ==============
模块,当前组,最大组
1,1,3
2,2,3
3,1,3
= ============运行5 ==============
模块,当前组,最大组
1,1,3
2,2,3
3,2,3
= ============运行6 ==============
模块,当前组,最大组
1,1,3
2,2,3
3,3,3
= ============运行7 ==============
模块,当前组,最大组
1,1,3
2,3,3
3,1,3
= ============运行8 ==============
模块,当前组,最大组
1,1,3
2,3,3
3,2,3
= ============运行9 ==============
模块,当前组,最大组
1,1,3
2,3,3
3,3,3
= ============运行10 ============== //////这是问题所在
模块,当前组,最大组
1,1,3
2,4,3
3,1,3

1 个答案:

答案 0 :(得分:1)

新答案:

首先,可能组合的数量是每个模块中组数的乘积。例如,如果有三个模块,分别包含5个,2个和7个组,那么有5 * 2 * 7 = 70种可能的组合。叫这个TOTALCOMBOS。

所以,如果你想迭代所有可能的组合,你可以从0循环到TOTALCOMBOS-1。

for I in 0..TOTALCOMBOS-1 do
    COMBO = (convert I to a combination)
    (do something with COMBO)

现在,要将索引转换为组合,有助于将整数索引视为从右到左的“数字”列表。这是最容易看出每个模块是否有10个组,并且组号是从0开始而不是1.然后可以读取整数468作为列表(8,6,4),这意味着来自模块1的组8,模块2中的第6组和模块3中的第4组。在伪代码中,将索引转换为组合将类似于

DIGITS = I
for M in 1..(number of modules) do
   D = DIGITS mod (number of groups in module M)
   DIGITS = DIGITS / (number of groups in module M)
   (add group D from module M to the current combination)

如果您希望组号从1开始而不是0,那么只需在最后一行使用组D + 1,而不是组D.

老答案:

使用递归。递归函数可以获取模块列表,并返回组合列表。每个组合将包含输入列表中每个模块的一个组。

作为基本情况,如果模块列表为空,则返回一个空的组合列表。

否则,让M成为第一个模块,让REST成为其余模块。在REST上调用递归函数以获取其余模块的所有组合(调用此COMBOS组合列表)。请注意,COMBOS中的这些组合包含来自M的组。

现在,我们将列出所有组合,这次包括来自M的组。将列表ANSWERS初始化为空。使用两个嵌套循环。对于M中的每个G组,以及COMBOS中的每个组合C,将G添加到C,并将此扩展组合添加到ANSWERS。

返回答案。

(假设:没有组出现在多个模块中,或者出现在同一个模块中两次。模块列表中不会出现多次模块。如果需要,可以放松这些假设,但是你需要定义什么你希望这些行为在这些情况下。)

(评论1:我上面说过“list”,但所有这些列表都可以很容易地成为数组或其他类型的容器。)

(评论2:我说“将G添加到C”,重要的是C本身不能被更改,因为它将被重复使用多次,对于M中的每个组一次。)