给出一组values=1,5,10,20,50,100的钞票,那么随机分配这些钞票的最佳方法是什么?我不想使用模数,然后通过添加更大的音符来查找余数。我希望它是随机的,以便它可能有一个更自然的分布,在其中纸币组成的总和。
目前,我正在这样做:
int temp = totalAmount;
for (int i = 0; i < values.Length; i++)
{
amounts[i] = temp / values[i];
temp %= values[i];
}这将给我一个3x100、1x50、1x10、3x1的便笺分发版,但我更希望它类似于1x100、3x50、2x20、6x10、13x13,尽管我不能想出一个好的策略。
发布于 2020-04-15 20:07:07
如果你真的希望它是随机的,你可以这样做:
var rnd = new Random();
int currentValue = 0;
var selectedNotes = new List<int>();
int[] notes = {1, 5, 10, 20, 50, 100};
int targetValue = 363;
while (currentValue < targetValue)
{
int v = rnd.Next(0, notes.Length);
if (currentValue + notes[v] > targetValue)
{
continue;
}
selectedNotes.Add(notes[v]);
currentValue += notes[v];
}
foreach (var note in selectedNotes.GroupBy(z => z).Select(z => new {BankNote = z.Key, Quantity = z.Count()})
.OrderByDescending(z => z.BankNote))
{
Console.WriteLine($"{note.Quantity}x{note.BankNote}");
}发布于 2020-04-15 19:30:52
主要是为了挑战,为了看它是如何进行的,我编写了一个小类来计算所有可能的组合,然后您可以从这个桶中提取。
作为奖励,这将允许从列表中提取任意数量的唯一组合(删除)。
然而,我已经为每种音符类型设置了一个限制,例如。20倍没有任何限制,这将运行很长时间(或可能耗尽内存)。
public static void Main()
{
var C = new Combinations();
int targetValue = 363;
int limitPerNote = 20;
foreach(int v in new[] {1, 5, 10, 20, 50, 100})
{
int maxCnt = (int)(targetValue / v);
maxCnt = Math.Min(maxCnt, limitPerNote);
C.Add(v, maxCnt);
}
List<String> Results = new List<String>();
while(!C.Inc())
{
if(C.TotalValue==targetValue)
{
//Console.WriteLine(C.CurrentCombinationToString());
Results.Add(C.CurrentCombinationToString());
}
}
Console.WriteLine($"{Results.Count} combinations found");
Random random = new Random();
Console.WriteLine($"Random combination:");
Console.WriteLine(Results[random.Next(0, Results.Count)]);
}
public class Combinations
{
private List<CombinationItem> Items {get; set;} = new List<CombinationItem>();
public void Add(int value, int maxCount)
{
Items.Add(new CombinationItem() {Value=value, MaxCount = maxCount});
}
public bool Inc()
{
int i = Items.Count -1;
bool overflowFlag = true;
while(overflowFlag)
{
overflowFlag = Items[i].Inc();
if(overflowFlag) i--;
if(i<0) return true; // final overflow, last combination reached
}
return false; // return without final overflow
}
public int TotalValue
{get{ return Items.Sum((item) => item.Value * item.Count); }}
public string CurrentCombinationToString()
{
return String.Join(" + ", Items.
Where((item) => item.Count >0).
Select((item) => $@"{item.Count}x {item.Value}"));
}
}
public class CombinationItem
{
public int Value {get; set;}
public int Count {get; set;}
public int MaxCount {get; set;}
public bool Inc()
{
// returns true on overflow
Count++;
if(Count > MaxCount)
{
Count=0;
return true;
}
else
return false;
}
}发布于 2020-04-15 18:38:12
这对你是有用的:
Random random = new Random();
int[] values = { 1, 5, 10, 20, 50, 100 };
int[] amounts = new int[values.Length];
int totalAmount = 363;
int left = totalAmount;
while (left > 0)
{
int nextNote = random.Next(0, values.Length);
if (values[nextNote] < left)
{
left -= values[nextNote];
amounts[nextNote]++;
}
}https://stackoverflow.com/questions/61235921
复制相似问题