如何通过所有可能的组合来填充数组或变量集

时间:2017-08-18 12:27:22

标签: c#

这类问题可能已经得到了解答,但我不能超越我想用C#编写的小程序的构思过程。

我想做的是:

- 我有n = 100

- 我还有9个变量/ 9个数组

- 我希望获得在所有9个变量之间分配n的所有可能组合,例如:

v1 = 100;
v2 = 0;
v3 = 0;
v4 = 0;
v5 = 0;
v6 = 0;
v7 = 0;
v8 = 0;
v9 = 0;

v1 = 10;
v2 = 5;
v3 = 13;
v4 = 27;
v5 = 0;
v6 = 34;
v7 = 0;
v8 = 11;
v9 = 0;

我看过堆的algorythm,但它似乎不适合,或者我可能不理解完整的概念。

另外,计算组合数的方法是什么,产品方法是正确的吗?

编辑:我找到了使用在线工具找到延续的可能组合的数量。总数为“352 025 629 371”。是的,需要一段时间来完成所有这些。

3 个答案:

答案 0 :(得分:0)

这可能会让你入门。它只是暴力强迫所有的组合。

using System;
using System.Collections.Generic;
using System.Linq;

namespace Bob
{
    public class Program
    {
        private static IEnumerable<Combination> GetData()
        {
            for (int a = 0; a < 101; a++)
            {
                for (int b = 0; b < 101; b++)
                {
                    for (int c = 0; c < 101; c++)
                    {
                        for (int d = 0; d < 101; d++)
                        {
                            for (int e = 0; e < 101; e++)
                            {
                                for (int f = 0; f < 101; f++)
                                {
                                    for (int g = 0; g < 101; g++)
                                    {
                                        for (int h = 0; h < 101; h++)
                                        {
                                            for (int i = 0; i < 101; i++)
                                            {
                                                var sum = a + b + c + d + e + f + g + h + i;

                                                if (sum == 100)
                                                {
                                                    yield return new Combination(a, b, c, d, e, f, g, h, i);
                                                }
                                                else if (sum > 100)
                                                {
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        static void Main(string[] args)
        {
            var sampleResults = GetData().Take(200); // this will show 200 (remove .Take(100) to show them all)

            foreach (var result in sampleResults)
            {
                Console.WriteLine(result);
            }
            Console.ReadLine();
        }
    }

    public class Combination
    {
        public readonly int V1;
        public readonly int V2;
        public readonly int V3;
        public readonly int V4;
        public readonly int V5;
        public readonly int V6;
        public readonly int V7;
        public readonly int V8;
        public readonly int V9;

        public Combination(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9)
        {
            V1 = v1;
            V2 = v2;
            V3 = v3;
            V4 = v4;
            V5 = v5;
            V6 = v6;
            V7 = v7;
            V8 = v8;
            V9 = v9;
        }

        public override string ToString()
        {
            return string.Format("{0} {1} {2} {3} {4} {5} {6} {7} {8}", V1, V2, V3, V4, V5, V6, V7, V8, V9);
        }
    }
}

答案 1 :(得分:0)

mjwills解决方案的替代方法是使用暴力破解的递归方法。

优化是不会运行所有内容,而是将搜索限制为最多100个数字 - 当前总和(因为如果当前总和是50,我们知道下一个数字不可能是&gt;因为那将总和超过100。)。

public class Program
{
    static void Main(string[] args)
    {
        var sampleResult2 = BruteForceCombinations(new List<int>(), new List<Combination>());

        foreach (var result in sampleResult2)
        {
            Console.WriteLine(result);
        }

        Console.ReadLine();
    }

    private static IEnumerable<Combination> BruteForceCombinations(List<int> listSoFar = null, List<Combination> validCombinations = null)
    {
        if (listSoFar.Count == 9)
        {
            if (listSoFar.Sum() == 100)
            {
                List<int> validCombinationList = new List<int>();
                validCombinationList.AddRange(listSoFar);

                validCombinations.Add(new Combination(validCombinationList));
            }
        }
        else
        {
            // Run from 0 to 100 - the sum of list entries so far + 1, as any number larger than that will create a sum larger than 100
            for (int i = 0; i < 100 - listSoFar.Sum() + 1; i++)
            {
                // Add the number to test the combination and remove after
                // The combination is added if we hit one that sums to 100.
                listSoFar.Add(i);
                BruteForceCombinations(listSoFar, validCombinations);
                listSoFar.RemoveAt(listSoFar.Count-1);
            }
        }

        return validCombinations;
    }
}

public class Combination
{
    private readonly List<int> numbers; 

    public Combination(List<int> numbers)
    {
        this.numbers = numbers;
    } 

    public override string ToString()
    {
        return string.Join(";", this.numbers);
    }
}

我没有机会完成整个程序,但我认为它会产生正确的结果。至少,显示了递归的想法。

答案 2 :(得分:-1)

如果我是你,我会检查回溯算法。它实际上构建了你需要的东西,但据我所知它耗费内存。

关于组合的数量,有公式: 100个组合中的100个组合等于:100!/ [10!*(100-10)!]