/// <summary> /// Solves the knapsack problem. /// </summary> /// <param name="maxWeight">The maximum weight.</param> /// <param name="itemList">The item list.</param> /// <param name="valueMatrix">The value matrix.</param> /// <param name="keepMatrix">The keep matrix.</param> /// <param name="itemCount">The item count.</param> private static void SolveKnapsackProblem( long maxWeight, IList <IItem> itemList, InfiniteTwoDimensionalSparseMatrix <long> valueMatrix, InfiniteTwoDimensionalSparseMatrix <bool> keepMatrix, int itemCount) { for (int currentFileIndex = 1; currentFileIndex <= itemCount; currentFileIndex++) { long weightAtPreviousIndex = itemList[currentFileIndex - 1].Weight; long valueAtPreviousIndex = itemList[currentFileIndex - 1].Value; for (int currentWeight = 0; currentWeight <= maxWeight; currentWeight++) { long newProspectiveValue = valueAtPreviousIndex + valueMatrix[currentFileIndex - 1, currentWeight - weightAtPreviousIndex]; long oldValue = valueMatrix[currentFileIndex - 1, currentWeight]; if (weightAtPreviousIndex <= currentWeight && newProspectiveValue > oldValue) { valueMatrix[currentFileIndex, currentWeight] = newProspectiveValue; keepMatrix[currentFileIndex, currentWeight] = true; } else { valueMatrix[currentFileIndex, currentWeight] = oldValue; } } } }
/// <summary> /// Solves the Knapsack problem /// </summary> /// <param name="items">The items to put into the knapsack</param> /// <param name="maxWeight">The maximum weight the knapsack can hold</param> /// <returns> /// The items to put into the knapsack /// </returns> public IEnumerable <IItem> Solve(IEnumerable <IItem> items, long maxWeight) { if (items.Any() == false) { return(Enumerable.Empty <IItem>()); } IList <IItem> itemList = items.ToList(); var valueMatrix = new InfiniteTwoDimensionalSparseMatrix <long>(); var keepMatrix = new InfiniteTwoDimensionalSparseMatrix <bool>(); int itemCount = itemList.Count; SolveKnapsackProblem(maxWeight, itemList, valueMatrix, keepMatrix, itemCount); return(Package(itemList, keepMatrix, maxWeight)); }
/// <summary> /// Packages the specified item list. /// </summary> /// <param name="itemList">The item list.</param> /// <param name="keepMatrix">The keep matrix.</param> /// <param name="maxWeight">The maximum weight.</param> /// <returns>The items packed up into a knapsack</returns> private static IEnumerable <IItem> Package( IList <IItem> itemList, InfiniteTwoDimensionalSparseMatrix <bool> keepMatrix, long maxWeight) { int itemCount = itemList.Count; var knapsackItems = Enumerable.Empty <IItem>(); long upperBound = maxWeight; for (int i = itemCount; i > 0; i--) { if (keepMatrix[i, upperBound]) { IItem currentItem = itemList[i - 1]; knapsackItems = knapsackItems.Append(currentItem); upperBound -= currentItem.Weight; } } return(knapsackItems); }