public ISack <T> Solve(IList <IItem <T> > items, long maxWeight)
        {
            var resultMatrix = new TwoDimensionalMatrix <long>();
            var keepMatrix   = new TwoDimensionalMatrix <bool>();

            var weightArray = (from w in items select w.Weight).ToList();
            var valueArray  = (from v in items select v.Value).ToList();

            var itemCount = items.Count;

            for (var i = 1; i <= itemCount; i++)
            {
                var weightAtIndex = weightArray[i - 1];
                var valueAtIndex  = valueArray[i - 1];
                for (var w = 0; w <= maxWeight; w++)
                {
                    var newValue      = resultMatrix[i, w - 1] + valueAtIndex;
                    var previousValue = resultMatrix[i - 1, w];
                    if (weightAtIndex <= w && newValue > previousValue)
                    {
                        resultMatrix[i, w] = newValue;
                        keepMatrix[i, w]   = true;
                    }
                    else
                    {
                        resultMatrix[i, w] = previousValue;
                    }
                }
            }

            var duplicateSack = new DuplicateAllowedSack <T>(maxWeight);

            /*
             * 1. Find the max value at the max weight
             * 2. Figure out which items added to the max value
             * 3. Count them
             * 4. Add them to the bag
             */
            for (var i = 1; i <= itemCount; i++)
            {
                if (keepMatrix[i, maxWeight])
                {
                    //Count how many times we should add it to the sack
                    for (var j = 0; j <= maxWeight; j++)
                    {
                        if (keepMatrix[i, j])
                        {
                            duplicateSack.AddItem(items[i - 1]);                             //The index for the item array is off by one
                        }
                    }
                }
            }

            return(duplicateSack);
        }
        public ISack <T> Solve(IList <IItem <T> > items, long maxWeight)
        {
            var resultMatrix = new TwoDimensionalMatrix <long>();
            var keepMatrix   = new TwoDimensionalMatrix <bool>();

            var itemCount = items.Count;

            for (var i = 1; i <= itemCount; i++)
            {
                var weightAtIndex = items[i - 1].Weight;
                var valueAtIndex  = items[i - 1].Value;

                for (var w = 0; w <= maxWeight; w++)
                {
                    var newValue = valueAtIndex + resultMatrix[i - 1, w - weightAtIndex];
                    var oldValue = resultMatrix[i - 1, w];
                    if (weightAtIndex <= w && newValue > oldValue)
                    {
                        resultMatrix[i, w] = newValue;
                        keepMatrix[i, w]   = true;
                    }
                    else
                    {
                        resultMatrix[i, w] = oldValue;
                    }
                }
            }

            var defaultSack = new Sack <T>(maxWeight);

            var upperBound = maxWeight;

            for (var i = items.Count; i > 0; i--)
            {
                if (keepMatrix[i, upperBound])
                {
                    defaultSack.AddItem(items[i - 1]);
                    upperBound -= items[i - 1].Weight;
                }
            }

            return(defaultSack);
        }