/// <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)
        {
            IList <IItem> itemList = items.ToList();

            var smallerSolutionList  = new OneDimensionalSparseArray <long>();
            var intermediateSolution = new OneDimensionalSparseArray <long>();
            var memoList             = new OneDimensionalSparseArray <long>();
            var keepMatrix           = new TwoDimensionalSparseMatrix <bool>();

            SolveUnboundedKnapsack(maxWeight, itemList, ref smallerSolutionList, ref intermediateSolution, ref memoList, ref keepMatrix);

            return(Package(itemList, keepMatrix, maxWeight));
        }
        /// <summary>
        /// Solves the unbounded knapsack.
        /// </summary>
        /// <param name="maxWeight">The maximum weight.</param>
        /// <param name="itemList">The item list.</param>
        /// <param name="smallerSolutionList">The smaller solution list.</param>
        /// <param name="intermediateSolutionList">The intermediate solution list.</param>
        /// <param name="memoList">The memo list.</param>
        /// <param name="keepMatrix">The keep matrix.</param>
        private static void SolveUnboundedKnapsack(
            long maxWeight,
            IList <IItem> itemList,
            ref OneDimensionalSparseArray <long> smallerSolutionList,
            ref OneDimensionalSparseArray <long> intermediateSolutionList,
            ref OneDimensionalSparseArray <long> memoList,
            ref TwoDimensionalSparseMatrix <bool> keepMatrix)
        {
            for (long weight = 1; weight <= maxWeight; weight++)
            {
                for (int itemIndex = 0; itemIndex < itemList.Count; itemIndex++)
                {
                    IItem currentItem = itemList[itemIndex];
                    if (weight >= currentItem.Weight)
                    {
                        smallerSolutionList[itemIndex] = memoList[weight - currentItem.Weight];
                    }
                    else
                    {
                        smallerSolutionList[itemIndex] = 0;
                    }
                }

                for (int itemIndex = 0; itemIndex < itemList.Count; itemIndex++)
                {
                    IItem currentItem = itemList[itemIndex];
                    if (weight >= currentItem.Weight)
                    {
                        intermediateSolutionList[itemIndex] = smallerSolutionList[itemIndex] + currentItem.Value;
                    }
                    else
                    {
                        intermediateSolutionList[itemIndex] = 0;
                    }
                }

                long fileIndexOfMaxValue = 0;
                memoList[weight] = intermediateSolutionList[0];

                for (int itemIndex = 1; itemIndex < itemList.Count; itemIndex++)
                {
                    if (intermediateSolutionList[itemIndex] > memoList[weight])
                    {
                        memoList[weight]    = intermediateSolutionList[itemIndex];
                        fileIndexOfMaxValue = itemIndex;
                    }
                }

                keepMatrix[fileIndexOfMaxValue, weight] = true;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Enumerator"/> class.
 /// </summary>
 /// <param name="parent">The parent.</param>
 public Enumerator(OneDimensionalSparseArray <T> parent)
 {
     _parent = parent;
 }