Cela peut être facile si vous essayez de stocker d'abord les gros objets et de compléter avec les plus petits.
Voici un code rapide que j'ai créé pour vous, et qui fonctionne bien :
static void Main(string[] args)
{
// data
List<Int32> listElement = new List<Int32>() { 10, 20, 10, 30, 45, 10, 20, 30, 40, 50, 60, 40, 30, 50, 60, 70, 80, 90, 20, 30, 10, 50, 60, 40, 60, 80, 90, 60, 80, 70, 80, 90, 90, 50 };
Int32 MaxStack = 180;
// result
List<List<Int32>> listResult = new List<List<Int32>>();
// process
foreach (Int32 element in listElement.OrderByDescending(i => i))
{
List<Int32> listToStore = listResult.Where(l => l.Sum() + element <= MaxStack).FirstOrDefault();
if (listToStore == null)
{
listToStore = new List<Int32>();
listResult.Add(listToStore);
}
listToStore.Add(element);
}
// view
foreach (List<Int32> list in listResult)
{
Console.Write("List " + (listResult.IndexOf(list) + 1) + "[total " + list.Sum() + "]: ");
foreach (Int32 element in list)
{
Console.Write(element.ToString() + " ");
}
Console.WriteLine();
}
Console.ReadKey();
}
Pour l'exemple, c'est en console, avec l'objet Int32, mais c'est la même chose pour les objets complexes.
Il suffit de lire votre liste d'objets du plus grand au plus petit, et de trouver la première liste de magasin qui peut le stocker.
Le résultat est :
List 1[total 180]: 90 90
List 2[total 180]: 90 90
List 3[total 180]: 80 80 20
List 4[total 180]: 80 80 20
List 5[total 180]: 70 70 40
List 6[total 180]: 60 60 60
List 7[total 180]: 60 60 50 10
List 8[total 180]: 50 50 50 30
List 9[total 175]: 45 40 40 30 20
List 10[total 90]: 30 30 10 10 10
Edit : Si vous voulez autant que la liste à 180, c'est un code (rapide et facile) que vous pouvez ajouter entre le processus et la vue :
// switching element for better fill
List<List<Int32>> unfilledlist = listResult.Where(l => l.Sum() < MaxStack).ToList();
// truncate original result
unfilledlist.ForEach(l => listResult.Remove(l));
while (unfilledlist != null && unfilledlist.Count > 1)
{
List<Int32> list = unfilledlist.First();
unfilledlist.Remove(list);
foreach (Int32 element in list)
{
Int32 needed = MaxStack - list.Sum() + element;
Boolean isFound = false;
foreach (List<Int32> smallerlist in unfilledlist)
{
List<Int32> switchingList = new List<int>();
// searching how to fill what we needed
foreach (Int32 e in smallerlist.OrderByDescending(i => i))
{
if (e + switchingList.Sum() <= needed)
switchingList.Add(e);
}
// we found a possible switch
if (switchingList.Sum() == needed)
{
// moving first element
list.Remove(element);
smallerlist.Add(element);
// moving element
switchingList.ForEach(e => { smallerlist.Remove(e); list.Add(e); });
isFound = true;
break;
}
}
if (isFound)
break;
}
listResult.Add(list.OrderByDescending(i => i).ToList());
}
// completing result with lists that are not with sum 180
unfilledlist.ForEach(l => listResult.Add(l.OrderByDescending(i => i).ToList()));
Je ne suis pas satisfait de ce code, mais il semble fonctionner
Nouveau résultat :
List 1[total 180]: 90 90
List 2[total 180]: 90 90
List 3[total 180]: 80 80 20
List 4[total 180]: 80 80 20
List 5[total 180]: 70 70 40
List 6[total 180]: 60 60 60
List 7[total 180]: 60 60 50 10
List 8[total 180]: 50 50 50 30
List 9[total 180]: 40 40 30 30 20 10 10
List 10[total 85]: 45 30 10