diff --git a/src/algorithms/sets/knapsack-problem/Knapsack.js b/src/algorithms/sets/knapsack-problem/Knapsack.js index 5d1491110..dacaaeabb 100644 --- a/src/algorithms/sets/knapsack-problem/Knapsack.js +++ b/src/algorithms/sets/knapsack-problem/Knapsack.js @@ -122,32 +122,20 @@ export default class Knapsack { while (itemIndex > 0) { const currentItem = this.possibleItems[itemIndex]; - const prevItem = this.possibleItems[itemIndex - 1]; - - // Check if matrix value came from top (from previous item). - // In this case this would mean that we need to include previous item - // to the list of selected items. - if ( - knapsackMatrix[itemIndex][weightIndex] - && knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex] - ) { - // Check if there are several items with the same weight but with the different values. - // We need to add highest item in the matrix that is possible to get the highest value. - const prevSumValue = knapsackMatrix[itemIndex - 1][weightIndex]; - const prevPrevSumValue = knapsackMatrix[itemIndex - 2][weightIndex]; - if ( - !prevSumValue - || (prevSumValue && prevPrevSumValue !== prevSumValue) - ) { - this.selectedItems.push(prevItem); - } - } else if (knapsackMatrix[itemIndex - 1][weightIndex - currentItem.weight]) { - this.selectedItems.push(prevItem); + + // If the value differs from the row above, the current item was included. + if (knapsackMatrix[itemIndex][weightIndex] !== knapsackMatrix[itemIndex - 1][weightIndex]) { + this.selectedItems.push(currentItem); weightIndex -= currentItem.weight; } itemIndex -= 1; } + + // Check if the first item was also included. + if (knapsackMatrix[0][weightIndex] !== 0) { + this.selectedItems.push(this.possibleItems[0]); + } } // Solve unbounded knapsack problem. diff --git a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js index d322445a7..8a5918d2c 100644 --- a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js +++ b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js @@ -44,6 +44,25 @@ describe('Knapsack', () => { expect(knapsack.selectedItems[1].toString()).toBe('v4 w3 x 1'); }); + it('should solve 0/1 knapsack problem with no single-weight-1 item (issue #248)', () => { + const possibleKnapsackItems = [ + new KnapsackItem({ value: 3, weight: 2 }), + new KnapsackItem({ value: 4, weight: 3 }), + new KnapsackItem({ value: 5, weight: 4 }), + new KnapsackItem({ value: 7, weight: 5 }), + ]; + + const maxKnapsackWeight = 7; + + const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); + + knapsack.solveZeroOneKnapsackProblem(); + + expect(knapsack.totalValue).toBe(10); + expect(knapsack.totalWeight).toBe(7); + expect(knapsack.selectedItems.length).toBe(2); + }); + it('should solve 0/1 knapsack problem with impossible items set', () => { const possibleKnapsackItems = [ new KnapsackItem({ value: 5, weight: 40 }),