最直接的方法是根据每个要生产的物品在要生产的物品总数中的比例(所有组的总和)按比例分配 50 个可用插槽。
I.E.:让我们假设这 4 行是此时要生产的所有项目。
Product A | Variant A | Color Red: 32 items
Product A | Variant A | Color Blue: 15 items
Product A | Variant B | Color Red: 12 items
Product B | Variant C | Color Black: 5 items
必须按降序对组进行排序,以确保编号最大的组首先被分配用于生产。
那么要生产的物品总数为 32+15+12+5 = 64。
基于每个组的比例(权重)分配可用插槽将是:
50* 32/64 =25 items for the 1st group
50* 15/64 = 11 items for the 2nd group
50* 12/64 = 9 items for the 3rd group
50* 5/64 =3 items for the 4th group
然后剩余部分(由于四舍五入)可以递归地或整个组项目的其余部分分布。
这里是递归剩余分配的实现,直到它被完全分配,并且根据每个组的剩余需求在每轮递归中更新比率。
public class Group
{
public string Product { get; set; }
public string Variant { get; set; }
public string Color { get; set; }
public int NeededToProduce { get; set; }
public int AllocatedForProd { get; set; }
}
public class Calculation
{
public Calculation()
{
AllocateProdSlots(this._prodSlots, this._groups);
}
private List<Group> _groups = new List<Group>()
{
new Group () {Product = "A", Variant = "A", Color = "Red", NeededToProduce = 32 , AllocatedForProd = 0},
new Group () {Product = "A", Variant = "A", Color = "Blue", NeededToProduce = 15 , AllocatedForProd = 0},
new Group () {Product = "A", Variant = "B", Color = "Red", NeededToProduce = 12 , AllocatedForProd = 0},
new Group () {Product = "B", Variant = "C", Color = "Black", NeededToProduce = 5 , AllocatedForProd = 0},
} ;
private int _prodSlots = 50;
private void AllocateProdSlots( int remainingProdSlots, List<Group> groups)
{
groups = groups.OrderByDescending(g => g.NeededToProduce).ToList<Group>();
decimal total = GetTotalNumberOfItemsInGroups();
foreach(var g in groups)
{
if (remainingProdSlots > 0)
{
int remainingNeedGroup = g.NeededToProduce - g.AllocatedForProd;
int allocation = Decimal.ToInt32( remainingNeedGroup / total * remainingProdSlots);
if (allocation <= remainingNeedGroup)
g.AllocatedForProd += allocation;
else g.AllocatedForProd += remainingNeedGroup;
if (allocation == 0 && remainingNeedGroup > 0 && remainingProdSlots > 0) //rounded down
{
g.AllocatedForProd += 1; //give such group 1 slot
allocation = 1;
}
remainingProdSlots -= allocation;
Console.WriteLine($" NumberToProduce {g.NeededToProduce}; AllocatedForProd {g.AllocatedForProd}; remainingProdSlots {remainingProdSlots};");
}
else break;
}
if (remainingProdSlots > 0) //we still have a remainder after the above allocation round - call another round to sart on the remaining slots
{
Console.WriteLine($"Remainder to be allocated in the next round {remainingProdSlots}");
AllocateProdSlots(remainingProdSlots, groups);
}
}
private decimal GetTotalNumberOfItemsInGroups()
{
return _groups.Sum(g => g.NeededToProduce);
}
}