Algorithm 找到将集合划分为给定大小子集的所有方法

Algorithm 找到将集合划分为给定大小子集的所有方法,algorithm,combinatorics,Algorithm,Combinatorics,这并不复杂,但我就是不知道怎么做。 我有一组对象,假设它们是数字。我需要检查N个群的所有可能性(我们可以假设集合中有3个群,9个对象),其中群内的顺序不重要({1,2,3},{2,1,3},{3,2,1}等是相同的),群的顺序不重要([{1,2,3},{4,5,6},{2,1,3},{4,5,6})与[{5,4,6},{2,1,3}])。 我正在用C#编写代码,但实际上我没有什么可以展示的。我最接近的想法是包含了大量fors和ifs我使用的解决方案将元素按顺序排列;这避免了任何重复的问题。它使用

这并不复杂,但我就是不知道怎么做。
我有一组对象,假设它们是数字。我需要检查N个群的所有可能性(我们可以假设集合中有3个群,9个对象),其中群内的顺序不重要({1,2,3},{2,1,3},{3,2,1}等是相同的),群的顺序不重要([{1,2,3},{4,5,6},{2,1,3},{4,5,6})与[{5,4,6},{2,1,3}])。
我正在用C#编写代码,但实际上我没有什么可以展示的。我最接近的想法是包含了大量fors和ifs我使用的解决方案将元素按顺序排列;这避免了任何重复的问题。它使用递归和回溯来找到所有的解决方案

避免复制解决方案的关键限制是,除非所有编号较低的分区都非空,否则不能将元素放入
n
th分区

考虑你的问题,9个学生在3个分区。我们从三个空的集合开始

{} {} {}
我们现在需要将学生[1,2,3,4,5,6,7,8,9]放入这个分区集中。调用我们的函数

place({ {}, {}, {} }, [1, 2, 3, 4, 5, 6, 7, 8, 9])
我们把学生按顺序排列。学生1只有一个地方可以去:第一个分区。否则,我们将违反限制

place({ {1}, {}, {} }, [2, 3, 4, 5, 6, 7, 8, 9])
学生2可以进入前两个分区中的任何一个(即,您需要一个迭代循环来覆盖法律可能性)。从这里开始,您将循环执行两个递归调用:

place({ {1, 2}, {}, {} }, [3, 4, 5, 6, 7, 8, 9])
place({  {1},  {2}, {} }, [3, 4, 5, 6, 7, 8, 9])
在第一次调用中,
3
还不能进入第三个分区;在第二次呼叫中,它可以去任何地方

你知道这是怎么回事吗?当分区填满时(我推断每组最多有3名学生),您还需要检查完整的组。最后,每次你安排最后一名学生时,你都有一个有效的、独特的安排


编码留给读者作为练习。:-)

这是我昨天写的。生成所有解决方案需要很多时间,但它是有效的。我想如果我使用一些树来存储元素(现在每个新组都会与所有现有组进行比较),我可以使它更快

编辑:事实上,现在当我考虑它时,我不确定是否有可能的重复。我写过,当我有for循环通过所有元素时。也许我可以去掉“如果”来加快速度。当我可以使用笔记本电脑时,我会检查一下
没有重复。现在速度很快,结果似乎还不错

public class Group<T> : IComparable<Group<int>>
{
    public Group(IEnumerable<T> elements)
    {
        Elements = elements.OrderBy(n => n).ToArray();
    }
    public T[] Elements { get; }

    public bool Equals(Group<T> other)
    {
        if (object.ReferenceEquals(this, other))
            return true;
        //assume number of elements in groups are equal
        for (int i = 0; i < Elements.Length; i++)
            if (!Elements[i].Equals(other.Elements[i]))
                return false;
        return true;
    }


    public int CompareTo(Group<int> other)
    {
        int[] elements = Elements as int[];
        for (int i = 0; i < Elements.Length; i++)
        {
            if (elements[i] < other.Elements[i])
                return -1;
            else if (elements[i] > other.Elements[i])
                return 1;
        }

        return 0;
    }

    public override string ToString()
    {
        string result = "{";
        for (int i = 0; i < Elements.Length; i++)
            result += Elements[i] + (i == Elements.Length - 1 ? "" : ", ");
        result += "}";
        return result;
    }
}
class Program
{
    static void Main(string[] args)
    {
        int[] allElements = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        List<Group<int>> singleGroupCombinations = new List<Group<int>>();
        for (int i = 0; i < allElements.Length; i++)
        {
            for (int j = i + 1; j < allElements.Length; j++)
            {
                for (int k = j + 1; k < allElements.Length; k++)
                {
                    Group<int> newGroup = new Group<int>(new[]
                    {
                        allElements[i], allElements[j], allElements[k]
                    });
                    singleGroupCombinations.Add(newGroup);
                }
            }
        }


        List<Group<Group<int>>> groupsCombinations = new List<Group<Group<int>>>();
        for (int i = 0; i < singleGroupCombinations.Count; i++)
        {
            for (int j = i+1; j < singleGroupCombinations.Count; j++)
            {
                for (int k = j+1; k < singleGroupCombinations.Count; k++)
                {
                    Group<Group<int>> newGroup = new Group<Group<int>>(new[]
                    {
                        singleGroupCombinations[i], singleGroupCombinations[j], singleGroupCombinations[k]
                    });
                    groupsCombinations.Add(newGroup);
                }
            }
        }
        //all groups combinations in groupCombinations variable
    }
}
公共类组:i可比较
{
公共组(IEnumerable元素)
{
Elements=Elements.OrderBy(n=>n.ToArray();
}
公共T[]元素{get;}
公共布尔等于(其他组)
{
if(object.ReferenceEquals(this,other))
返回true;
//假设组中的元素数相等
for(int i=0;i其他.elements[i])
返回1;
}
返回0;
}
公共重写字符串ToString()
{
字符串结果=“{”;
for(int i=0;i
组大小是否始终为3?或者这只是巧合?那么你想要实现什么呢是否要检查这些组是否包含相同的数字?@Matt这不是正确的副本。(我想)是的,但回答不好。我很确定某个地方有个傻瓜,但我的搜索失败了。@raven22122122122121你说得对,我忘了提到-组中的元素数等于组中的元素数。@Ibrahim Ali在单个场景中,一个元素不能在多个组中,如果你是这样问的话。你可以想象我有一个班级,我想创建所有可能的学生群体。你应该使用@Prune的解决方案。你现在做得快多了。我看到了不必要的比较,觉得你还在做一些不同的事情。啊,好吧:)