【问题标题】:how to get all combinations from a array reaching a certain number?如何从数组中获取所有组合达到一定数量?
【发布时间】:2018-02-02 11:53:25
【问题描述】:

我正在尝试获得至少达到 100 的所有组合。如果将一个组合添加到另一个组合中,则 10+10+10+10+10+10+10+10+10+10(100)>= 100,还有 20+20+20+20+10+15(105)>=100。但是现在它只显示了一些,因为我不知道我怎样才能让他显示所有可能的组合。

我会在一段时间内使用 for 循环,因此它会一直添加到超过 'GETALTEBEREIKEN' 为止。但它会在添加完所有内容后进行检查。即使添加了它,我也不会得到 10*10。因为它只会转到数组中的下一个数字。所以它并没有给我所有的组合。

static void Main(string[] args)
    {
        const int TOTAALGETALLEN = 3;
        const int GETALTEBEREIEKEN = 100;
        int[] Getallen = new int[TOTAALGETALLEN];
        Getallen[0] = 10;
        Getallen[1] = 15;
        Getallen[2] = 20;
        int totaal = 0;
        string GebruikteGetallen;

        for(int i = 0; i < TOTAALGETALLEN; i++)
        {
            totaal = Getallen[i];
            GebruikteGetallen = i + ", ";
            while (totaal<GETALTEBEREIEKEN)
            {

                for(int j = 0; j < TOTAALGETALLEN; j++)
                {
                    totaal += Getallen[j];
                    GebruikteGetallen += j + ", ";
                }
            }
            Console.WriteLine(GebruikteGetallen);
            Console.WriteLine(totaal);
        }
        Console.ReadLine();  
    }

它应该是满足标准的子集(一组元素的组合)。

我还发现了这个:

    static void Main(string[] args)
    {
        int[] set = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        foreach (string s in GetCombinations(set, 18, ""))
        {
            Console.WriteLine(s);
        }
        Console.ReadLine();
    }
    public static IEnumerable<string> GetCombinations(int[] set, int sum, string values)
    {
        for (int i = 0; i < set.Length; i++)
        {
            int left = sum - set[i];
            string vals = set[i] + "," + values;
            if (left == 0)
            {
                yield return vals;
            }
            else
            {
                int[] possible = set.Take(i).Where(n => n <= sum).ToArray();
                if (possible.Length > 0)
                {
                    foreach (string s in GetCombinations(possible, left, vals))
                    {
                        yield return s;
                    }
                }
            }
        }
    }

但这不会让我再次使用相同的号码。也许它会对你的答案有所帮助。

【问题讨论】:

  • 这里通常不欢迎就某些学校项目寻求帮助的问题。我建议你向你的老师寻求帮助。
  • 项目应该做什么,它做了什么?
  • @RobAnthony 我需要看看有哪些可能的组合,如果超过 100 就可以了,但如果它已经超过 100 并且您广告更像另一个 10,您将得到 110,那只会“成本”更多。最后,Getallen 的每个 Getal 都会得到自己的“成本”,这就是为什么我需要知道使用了哪些数字。所以我可以计算出最便宜的选择。
  • 实际上,如果一个问题是明确的,如果它表明有人试图回答它,我认为为什么问这个问题是没有问题的——学校项目问题不纯粹是由定义不受欢迎。当问题只是被抛到这里而没有尝试回答时,它是不受欢迎的。我认为这个问题需要编辑,以使其更清楚它试图做什么以及目前出了什么问题。
  • 我还是不明白你在问什么。您是否想要 10、15 和 20 的所有不同组合至少达到 100?

标签: c# arrays combinations


【解决方案1】:

好的,我已经写了一个程序来解决这个问题。

因为你想成为变量,所以我使用递归而不是堆叠循环。 我还添加了许多 cmets 以便更容易理解它是如何工作的。 如果您有正确的解决方案,请检查结果是否正常。

internal class Program {
    public static void Main(string[] args) {
        // these are the same numbers, but you can replace or add some
        const int limit = 100;
        // if you don't know what a dictionary does you should google that
        var resources = new Dictionary<Good, int>();
        // this is the price of the resource
        resources[Good.Copper] = 20;
        resources[Good.Tin] = 15;
        resources[Good.Iron] = 10;
        //resources[Good.Paper] = 8;
        //resources[Good.Plastic] = 6;
        //resources[Good.Water] = 2;

        // Now we want to calculate all possible combinations.
        // We can not just put some loops into each other because when we have 4 instead of 3 resources we would need 4 loops.
        // Instead we will use some concept called recursion.

        // First we sort the resources from expensive to cheap
        var sortedResources = resources.OrderByDescending(x => x.Value);
        // all combinations will be stored in here
        var allSolutions = new List<List<KeyValuePair<Good, int>>>();
        // We will start with the maximum amount of the most expensive good and then lower its amount and check all amount of the other goods.

        var calculator = new CombinationCalculator(limit, sortedResources.ToList(), allSolutions);
        calculator.CalculateCombinationsRecursive(0, 0, new List<KeyValuePair<Good, int>>());
        Console.WriteLine("\nAll solutions calculated, " + allSolutions.Count + " combinations found.");
        Console.ReadKey();
    }
}

这是不同的资源

internal enum Good {
    Copper = 1,
    Tin = 2,
    Iron = 3,
    Paper = 4,
    Plastic = 5,
    Water = 6
}

这个类正在计算组合。

internal class CombinationCalculator {
    private readonly List<List<KeyValuePair<Good, int>>> _allSolutions;
    private readonly int _limit;
    private readonly List<KeyValuePair<Good, int>> _sortedResources;


    /// <summary>
    ///     This class will calculate all combinations
    /// </summary>
    /// <param name="limit">The minimum cost (100 for example)</param>
    /// <param name="sortedResources">All resources and their individual price sorted descending.</param>
    /// <param name="allSolutions">all completed combinations of resources and each amount.</param>
    public CombinationCalculator(int limit, List<KeyValuePair<Good, int>> sortedResources, List<List<KeyValuePair<Good, int>>> allSolutions) {
        _limit = limit;
        _sortedResources = sortedResources;
        _allSolutions = allSolutions;
    }


    /// <summary>
    ///     Find all combinations recursive.
    /// </summary>
    /// <param name="index">The resource that should be added next.</param>
    /// <param name="currentPrice">The price what the resources that are already added cost.</param>
    /// <param name="resources">All resources that are already added and their amount.</param>
    internal void CalculateCombinationsRecursive(int index, int currentPrice, List<KeyValuePair<Good, int>> resources) {
        // we calculate the amount af this resource needed to get atleast the limit
        var maximumAmount = (int)Math.Ceiling((_limit - currentPrice) / (1.0 * _sortedResources[index].Value));

        // with maximum amount you have one combination already
        var firstCombi = resources.ToList();
        firstCombi.Add(new KeyValuePair<Good, int>(_sortedResources[index].Key, maximumAmount));
        Console.WriteLine("Found one combination: ");
        foreach(var res in firstCombi) {
            Console.Write(" " + res.Key + " * " + res.Value + ",");
        }
        Console.WriteLine(" price: " + (currentPrice + maximumAmount * _sortedResources[index].Value));
        _allSolutions.Add(firstCombi);

        // if this is already the last resource we can't add more
        if(index == _sortedResources.Count - 1) {
            return;
        }
        // now find all other possible combinations recursive
        for(var i = maximumAmount - 1; i >= 0; i--) {
            // since we add less than maximum amount we will need to fill the price with the other resources
            var newResources = resources.ToList();
            newResources.Add(new KeyValuePair<Good, int>(_sortedResources[index].Key, i));
            // this method calls itself recursive
            CalculateCombinationsRecursive(index + 1, currentPrice + i * _sortedResources[index].Value, newResources);
        }
    }
}

如果您有任何问题,请随时提出。

我希望这对你有用,如果你想测试其他东西,只需修改 main 方法的第一部分和枚举。

【讨论】:

  • 天啊,你正式成为我的英雄!这就像我希望它起作用一样。我什至可以进行更改,让它完全适用于我希望它使用的所有东西!疯狂的!非常感谢!!
  • 很高兴能为您提供帮助。
猜你喜欢
  • 1970-01-01
  • 2014-12-17
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
相关资源
最近更新 更多