In the 0–1 Knapsack problem, we are given a set of items, each with a weight and a value, and we need to determine the number of each item to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible.

Please note that the items are indivisible; we can either take an item or not (0-1 property). For example,

Input:
 
value = [ 20, 5, 10, 40, 15, 25 ]
weight = [ 1, 2, 3, 8, 7, 4 ]
int W = 10
 
Output: Knapsack value is 60
 
value = 20 + 40 = 60
weight = 1 + 8 = 9 < W

Practice this problem

The idea is to use recursion to solve this problem. For each item, there are two possibilities:

  1. Include the current item in the knapsack and recur for remaining items with knapsack’s decreased capacity. If the capacity becomes negative, do not recur or return -INFINITY.
  2. Exclude the current item from the knapsack and recur for the remaining items.

Finally, return the maximum value we get by including or excluding the current item. The base case of the recursion would be when no items are left, or capacity becomes 0.

 
The following C++, Java, and Python implementation finds the maximum value that can be attained with weight less than or equal to W recursively using the above relations:

C++


Download  Run Code

Output:

Knapsack value is 60

Java


Download  Run Code

Output:

Knapsack value is 60

Python


Download  Run Code

Output:

Knapsack value is 60

The time complexity of the above solution is exponential and occupies space in the call stack.
 

 
The above solution has an optimal substructure, i.e., the optimal solution can be constructed efficiently from optimal solutions of its subproblem. It also has overlapping subproblems, i.e., the problem can be broken down into subproblems, and each subproblem is repeated several times. To reuse the subproblem solutions, we can apply dynamic programming, in which subproblem solutions are memoized rather than computed over and over again.

Following is the memoized version in C++, Java, and Python, which follows the top-down approach since we first break the problem into subproblems and then calculate and store values.

C++


Download  Run Code

Output:

Knapsack value is 60

Java


Download  Run Code

Output:

Knapsack value is 60

Python


Download  Run Code

Output:

Knapsack value is 60

The time complexity of the above top-down solution is O(n.W) and requires O(n.W) extra space, where n is the total number of items in the input and W is the knapsack’s capacity.
 

 
We can also solve this problem in a bottom-up manner. In the bottom-up approach, we solve smaller subproblems first, then solve larger subproblems from them. The following bottom-up approach computes T[i][j], for each 1 <= i <= n and 0 <= j <= W, which is the maximum value that can be attained with weight less than or equal to j and using items up to first i items. It uses the value of smaller values i and j already computed. It has the same asymptotic runtime as Memoization but no recursion overhead.

The algorithm can be implemented as follows in C++, Java, and Python:

C++


Download  Run Code

Output:

Knapsack value is 60

Java


Download  Run Code

Output:

Knapsack value is 60

Python


Download  Run Code

Output:

Knapsack value is 60

The time complexity of the above bottom-up solution is O(n.W) and requires O(n.W) extra space, where n is the total number of items in the input and W is the knapsack’s capacity.