3

我有这个 c# 类,它计算n 选择 k,然后按字典顺序生成所有可能的组合。它还可以返回每个组合的订单号,例如:传递 [1,2,3,4,5] 将返回 1 给定 n 选择 k(30,5),142506 为 [26,27,28,29,30] .

有没有办法返回包含部分组合的所有订单号?因此,如果我通过 [1,2,3,4],它将返回:1,2,3,...25,26。

1: [1,2,3,4,5]
2: [1,2,3,4,6]
3: [1,2,3,4,7]
...
25: [1,2,3,4,29]
26: [1,2,3,4,30]

我需要这个来抽奖。我希望每张票都有它的组合订单号,并且我需要在抽出 5 个球时显示可能获胜者的总数。现在每张票都有实际的组合,我运行查询以获得部分获胜者,但我想优化这个过程。

4

2 回答 2

3

您需要的组合(n-d) choose (k-d)d固定抽奖次数。

当您生成它们时,它们不会有正确的数字(它们会跳过最后一个d数字而不是您想要的数字),而只是使用子列表的逆序映射重新编写您的组合:

(在伪 python 代码中,因为这根本与 C# 无关)

listing = [1, 2, ..., 30]
partial = [4, 7, 25]
draw_size = 5
remaining = listing - partial
reverse_order_mapping = [(index, item) in remaining.items_and_indexes]

n = listing.size  // 30
k = draw_size     // 5
d = partial.size  // 3

for comb in ((n-d) choose (k-d))
  actual_comb = comb.map(reverse_order_mapping)
  print actual_comb
end

然后,您只需使用生成的组合调用您的函数(如果需要,在对其进行排序之后)。

于 2012-06-27T18:23:52.440 回答
3

您需要一个函数,对于组合 [a, b, c, d, e],返回该组合的订单号。然后你可以得到组合集(可能的数字集减去已经选择的数字)选择(你还没有选择的数量),将已经选择的数字添加到每个组合中,重新排序每个组合,然后使用它获取订单号的函数。

编辑:这可能会有所帮助:saliu.com/bbs/messages/348.html

EDIT2:答案就在这里:How to calculate the index (lexicographical order) when the combination is given

EDIT3:我为此尝试了一些 C# 代码:

private IEnumerable<int[]> CombinationsFor(int n, int k);
private int CombinationsCount(int n, int k);

private int IndexFor(int n, int[] combination)
{
    int k = combination.Count();
    int ret = 0;

    int j = 0;
    for (int i = 0; i < k; i++)
    {
        for (j++; j < combination[i]; j++)
        {
            ret += CombinationsCount(n - j, k - i - 1);
        }
    }

    return ret;
}

private IEnumerable<int> PossibleCombinations(int n, int k, int[] picked)
{
    int m = picked.Count();

    int[] reverseMapping = Enumerable.Range(0, n)
        .Where(i=>!picked.Contains(i))
        .ToArray();

    return CombinationsFor(n-m, k-m)
        .Select(c => c
            .Select(x=>reverseMapping[x])
            .Concat(picked)
            .OrderBy(x=>x)
            .ToArray()
        )
        .Select(c => IndexFor(n, c));
}
于 2012-06-27T18:19:01.443 回答