我有一个编码/数学问题,我需要帮助翻译成C#。这是一个扑克筹码计算器,可以获取BuyIn,玩家数量以及每种颜色(有x种颜色)的筹码总量及其价值。
然后它会向您显示每个人可能的筹码组合,以等于买入。然后,用户可以选择他们想要使用的芯片组分发。最好用一个简单的例子来说明。
所以,可能的组合是:
R / B / G
等
我花了很多时间试图在C#/ .NET中提出一个算法来解决这个问题。我对可变因素感到磕磕绊 - 一组中通常只有3或4种不同的芯片颜色,但可能有任何数量。如果您有多个玩家,则必须在TotalChips / NumberOfPlayers之前计算。
我开始通过所有芯片的循环,然后从0循环到NumberOfChips以获得该颜色。这几乎是我花了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;
}
}
}
}
}
}
答案 0 :(得分:3)
这是一个实现,它读取芯片数量,芯片(它们的价值和金额)以及购买量,并以您的示例格式显示结果。我已经通过评论对其进行了解释,如果您有任何问题请与我联系。
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
输入3个筹码值:
1
2
5
输入3个筹码金额:
10个
10个
10个
10/0/0 /
8/1/0 /
6/2/0 /
5/0/1 /
4/3/0 /
3/1/1 /
2/4/0 /
1/2/1 /
0/5/0 /
0/0/2 /
答案 1 :(得分:2)
通过芯片种类的数量递归地解决问题。
对于基本情况,有多少种方式可以用零筹码进行$ 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;
}
}
答案 2 :(得分:1)
对于某些大型组合,这可能无法在有限时间内解决。 (这是一个NP问题)
http://en.wikipedia.org/wiki/Knapsack_problem
还有代码的链接?这可以帮助你。 希望这有点帮助。