代码之家  ›  专栏  ›  技术社区  ›  Rodney

帮助数学/编码一个集合的可能组合,以构成一个总数-C#

  •  3
  • Rodney  · 技术社区  · 15 年前

    我有一个编码/数学问题需要帮助翻译成C。这是一个扑克筹码计算器,它可以计算出每种颜色的筹码(有x种颜色)和它们的价值。

    然后,它会向你展示每个人的筹码组合,使之等于买入的筹码。然后用户可以选择他们想要使用的芯片组分布。最好用一个简单的例子来说明。

    • 玩家数量:1
    • 10个蓝筹股,价值2美元
    • 10块绿晶片,价值5美元

    R/B/G公司

    • 6/2/0
    • 4/3/0

    等。

    为了解决这个问题,我花了很多时间试图在C/NET中提出一个算法。我在可变因素上绊倒了-通常只有3或4种不同的芯片颜色在一套,但可能有任何数量。如果你有一个以上的球员,你必须计算到总筹码/球员人数。

    我从循环所有的芯片开始,然后从0循环到那个颜色的芯片数。这是我过去4个小时里一直呆的地方。。。我该如何编写代码来循环遍历x个数量的筹码,并检查筹码和的值,如果等于BuyIn,则将其添加到集合中?我需要彻底改变我的方法。。。

    有人能告诉我怎么解决这个问题吗?伪代码将工作-感谢您的任何建议!

    下面是我迄今为止的尝试-这是没有希望的(而且不会编译,只是一个例子来向你展示我的思维过程到目前为止)-可能最好不要看它,因为它可能会使你对解决方案产生偏见。。。

       private void SplitChips(List<ChipSuggestion> suggestions)
        {
    
            decimal valueRequired = (decimal)txtBuyIn.Value;
            decimal checkTotal = 0;
            ChipSuggestion suggestion;
    
            //loop through each colour
            foreach (Chip chip in (PagedCollectionView)gridChips.ItemsSource)
            {
                    //for each value, loop through them all again
                    foreach (Chip currentChip in (PagedCollectionView)gridChips.ItemsSource)
                    {
                        //start at 0 and go all the way up
                        for (int i = 0; i < chip.TotalChipsInChipset; i++)
                        {
                            checkTotal = currentChip.ChipValue * i;
    
                            //if it is greater than than ignore and stop
                            if (checkTotal > valueRequired)
                            {
                                break;
                            }
                            else
                            {
                                //if it is equal to then this is a match
                                if (checkTotal == valueRequired)
                                {
                                    suggestion = new ChipSuggestion();
                                    suggestion.SuggestionName = "Suggestion";
    
                                    chipRed.NumberPerPlayer = i;
                                    suggestion.Chips.Add(chipRed);
    
                                    chipBlue.NumberPerPlayer = y;
                                    suggestion.Chips.Add(chipBlue);
    
                                    chipGreen.NumberPerPlayer = 0;
                                    suggestion.Chips.Add(chipGreen);
    
                                    //add this to the Suggestion
                                    suggestions.Add(suggestion);
                                    break;
                                }
    
    
                        }
                    }
                }
            }
        }
    
    3 回复  |  直到 15 年前
        1
  •  4
  •   IVlad    15 年前

    下面是一个实现,它读取芯片数量、芯片(它们的价值和数量)和buyin,并以示例格式显示结果。我已经通过评论解释了,如果你有任何问题,请告诉我。

    class Test
    {
        static int buyIn; 
        static int numChips;
        static List<int> chips = new List<int>(); // chips[i] = value of chips of color i
        static List<int> amountOfChips = new List<int>(); // amountOfChips[i] = number of chips of color i
    
        static void generateSolutions(int sum, int[] solutions, int last)
        {
            if (sum > buyIn) // our sum is too big, return
                return;
    
            if (sum == buyIn) // our sum is just right, print the solution
            {
                for (int i = 0; i < chips.Count; ++i)
                    Console.Write("{0}/", solutions[i]);
                Console.WriteLine();
    
                return; // and return
            }
    
            for (int i = last; i < chips.Count; ++i) // try adding another chip with the same value as the one added at the last step. 
                                                     // this ensures that no duplicate solutions will be generated, since we impose an order of generation
                if (amountOfChips[i] != 0)
                {
                    --amountOfChips[i]; // decrease the amount of chips
                    ++solutions[i]; // increase the number of times chip i has been used
    
                    generateSolutions(sum + chips[i], solutions, i); // recursive call
    
                    ++amountOfChips[i]; // (one of) chip i is no longer used
                    --solutions[i]; // so it's no longer part of the solution either
                }
        }
    
        static void Main()
        {
            Console.WriteLine("Enter the buyin:");
            buyIn = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter the number of chips types:");
            numChips = int.Parse(Console.ReadLine());
            Console.WriteLine("Enter {0} chips values:", numChips);
            for (int i = 0; i < numChips; ++i)
                chips.Add(int.Parse(Console.ReadLine()));
    
            Console.WriteLine("Enter {0} chips amounts:", numChips);
            for (int i = 0; i < numChips; ++i)
                amountOfChips.Add(int.Parse(Console.ReadLine()));
    
            int[] solutions = new int[numChips];
    
            generateSolutions(0, solutions, 0);
        }
    } 
    

    输入buyin:
    10


    输入3个值:
    1


    输入3个筹码金额:
    10
    10
    10


    6/2/0/

    4/3/0/
    3/1/1/

    1/2/1/

        2
  •  2
  •   Quartermeister    15 年前

    按芯片的种类递归地分解问题。

    对于基本情况,有多少种方法可以让零筹码的X美元买入?如果X为零,有一种方法:没有筹码。如果X大于零,就没有办法了。

    现在我们需要解决N种芯片的问题,给出N-1的解。我们可以拿一种芯片,把每一个可能的芯片数目都考虑进去。例如,如果芯片是2美元,而买入价是5美元,那么尝试使用其中的0、1或2个。对于每一次尝试,我们只能使用剩余的N-1个芯片来弥补剩余的值。我们可以通过递归调用来解决这个问题,然后将当前芯片添加到它返回的每个解决方案中。

    private static IEnumerable<IEnumerable<Tuple<Chip, int>>> GetAllChipSuggestions(List<Chip> chips, int players, int totalValue)
    {
        return GetAllChipSuggestions(chips, players, totalValue, 0);
    }
    
    private static IEnumerable<IEnumerable<Tuple<Chip, int>>> GetAllChipSuggestions(List<Chip> chips, int players, int totalValue, int firstChipIndex)
    {
        if (firstChipIndex == chips.Count)
        {
            // Base case: we have no chip types remaining
            if (totalValue == 0)
            {
                // One way to make 0 with no chip types
                return new[] { Enumerable.Empty<Tuple<Chip, int>>() };
            }
            else
            {
                // No ways to make more than 0 with no chip types
                return Enumerable.Empty<IEnumerable<Tuple<Chip, int>>>();
            }
        }
        else
        {
            // Recursive case: try each possible number of this chip type
            var allSuggestions = new List<IEnumerable<Tuple<Chip, int>>>();
            var currentChip = chips[firstChipIndex];
            var maxChips = Math.Min(currentChip.TotalChipsInChipset / players, totalValue / currentChip.ChipValue);
            for (var chipCount = 0; chipCount <= maxChips; chipCount++)
            {
                var currentChipSuggestion = new[] { Tuple.Create(currentChip, chipCount) };
                var remainingValue = totalValue - currentChip.ChipValue * chipCount;
                // Get all combinations of chips after this one that make up the rest of the value
                foreach (var suggestion in GetAllChipSuggestions(chips, players, remainingValue, firstChipIndex + 1))
                {
                    allSuggestions.Add(suggestion.Concat(currentChipSuggestion));
                }
            }
            return allSuggestions;
        }
    }
    
        3
  •  1
  •   Quonux    15 年前

    http://en.wikipedia.org/wiki/Knapsack_problem

    还有代码链接吗?那对你有帮助。