生成组合如果物品只能组合一次

发布于 2025-01-26 15:06:05 字数 424 浏览 4 评论 0原文

假设我有n个项目。 3),那么a不能与b nor C一起使用。

现在,我想创建m-item组合,但是如果已经存在组合{a,b,c}(在这种情况下为m = 1,2,3,4,5,6,7,8,9,10},m = 3,然后可能的组合应为:

  • {1,2,3}
  • {4,5,6}
  • {7,8, 9}
  • 的组合
  • {10,1,2} - 这不是
  • 有效 所有项目总是处于不同的组合中
  • ...

我可以创建多少个组合?

我该如何系统地生成此类组合?

如果我允许两个项目可以组合两个不同的组合?,因此组合{1,2,3},{1,2,4}将有效。

Let's say I have N items. Now I want to create M-item combinations but if there already exist a combination {A,B,C} (in this case M=3), then A cannot be in another combination together with B nor C.

Example: N={1,2,3,4,5,6,7,8,9,10}, M=3, then possible combinations should be:

  • {1,2,3}
  • {4,5,6}
  • {7,8,9}
  • {10,1,2} - this is not a valid combination because 1 and 2 are already in a generated combination {1,2,3}
  • {10,1,4}
  • {2,5,8} - valid because all items were always in different combinations
  • ...

How many combinations I can create?

How could I systematically generate such combinations?

What if I allow that two items can be together in two different combinations? So combinations {1,2,3} and {1,2,4} would be valid.

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

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

发布评论

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

评论(2

总攻大人 2025-02-02 15:06:05

蛮力,但很快。在python中,但我相信:

from itertools import combinations as c

data = range(1,11)

already_seen = set()
result = set()

all_combos = c(data,3)

for combo in all_combos:
    pairs = set(c(combo, 2))
    if not pairs & already_seen:
        result.add(combo)
        already_seen.update(pairs)

print(result)

# {(3, 9, 10), (3, 5, 6), (1, 2, 3), (2, 8, 10), (1, 4, 5), (2, 5, 7), (2, 4, 6), (1, 8, 9), (1, 6, 7), (3, 4, 7)}

Brute force, but pretty quick. In python, but clear on approach, I believe:

from itertools import combinations as c

data = range(1,11)

already_seen = set()
result = set()

all_combos = c(data,3)

for combo in all_combos:
    pairs = set(c(combo, 2))
    if not pairs & already_seen:
        result.add(combo)
        already_seen.update(pairs)

print(result)

# {(3, 9, 10), (3, 5, 6), (1, 2, 3), (2, 8, 10), (1, 4, 5), (2, 5, 7), (2, 4, 6), (1, 8, 9), (1, 6, 7), (3, 4, 7)}
初吻给了烟 2025-02-02 15:06:05

我想您可以使用标准组合生成算法,只需添加二手对的验证(在Java中)(在Java,但很清楚如何移植到任何其他语言):

import java.util.*;
public class Test {
    public static void main(String[] args) {
        generateCombinations(3, 10);
    }
    public static void generateCombinations(int m, int n) {
        var used = new HashSet<Long>();
        var combination = new HashSet<Integer>();
        for (int i = 1; i <= n; i++) generateCombination(i, m, n, used, combination);
    }
    public static boolean generateCombination(int c, int m, int n, Set<Long> used, Set<Integer> comb) {
        for (Integer ci : comb) if (used.contains(getPair(ci.intValue(), c))) return false;
        boolean result = false;
        for (Integer ci : comb) used.add(getPair(ci.intValue(), c));
        comb.add(c);
        if (comb.size() < m) {
            for (int i = c + 1; i <= n; i++) {
                result |= generateCombination(i, m, n, used, comb);
                if (result && comb.size() >= 2) break;
            }
        } else {
            result = true;
            System.out.println(Arrays.toString(comb.toArray(new Integer[comb.size()])));
        }
        comb.remove(c);
        if (!result) for (Integer ci : comb) used.remove(getPair(ci.intValue(), c));
        return result;
    }
    public static long getPair(int a, int b) {
        return (((long) a) << 32L) | b;
    }
}

对于3-10,它会生成10个组合,我想它是最大数字在子集中,请随时证明我错了

[1, 2, 3]
[1, 4, 5]
[1, 6, 7]
[1, 8, 9]
[2, 4, 6]
[2, 5, 7]
[2, 8, 10]
[3, 4, 7]
[3, 5, 6]
[3, 9, 10]

它应该很容易扩展以支撑唯一的三重态,而不是对,只需生成字符串键,例如min(a,b,c) +“ _” +“ _” + middle(a,a, b,c) +“ _” + max(a,b,c)而不是位于comb 设置为使用的使用设置

I suppose you can use standard combination generation algorithm, just add validation for used pairs, like this (in java, but pretty clear how to port to any other language):

import java.util.*;
public class Test {
    public static void main(String[] args) {
        generateCombinations(3, 10);
    }
    public static void generateCombinations(int m, int n) {
        var used = new HashSet<Long>();
        var combination = new HashSet<Integer>();
        for (int i = 1; i <= n; i++) generateCombination(i, m, n, used, combination);
    }
    public static boolean generateCombination(int c, int m, int n, Set<Long> used, Set<Integer> comb) {
        for (Integer ci : comb) if (used.contains(getPair(ci.intValue(), c))) return false;
        boolean result = false;
        for (Integer ci : comb) used.add(getPair(ci.intValue(), c));
        comb.add(c);
        if (comb.size() < m) {
            for (int i = c + 1; i <= n; i++) {
                result |= generateCombination(i, m, n, used, comb);
                if (result && comb.size() >= 2) break;
            }
        } else {
            result = true;
            System.out.println(Arrays.toString(comb.toArray(new Integer[comb.size()])));
        }
        comb.remove(c);
        if (!result) for (Integer ci : comb) used.remove(getPair(ci.intValue(), c));
        return result;
    }
    public static long getPair(int a, int b) {
        return (((long) a) << 32L) | b;
    }
}

for 3-10 it generates 10 combinations and I suppose it is maximal number of subsets, feel free to prove me wrong

[1, 2, 3]
[1, 4, 5]
[1, 6, 7]
[1, 8, 9]
[2, 4, 6]
[2, 5, 7]
[2, 8, 10]
[3, 4, 7]
[3, 5, 6]
[3, 9, 10]

it should be moderately easy to extend it to support unique triplets instead of pairs, just generate string key like min(a,b,c) + "_" + middle(a,b,c) + "_" + max(a,b,c) instead of bitwise hack I used to speed up and add all from comb set into used set

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