C++ Program to Solve the 0-1 Knapsack Problem



In the 0-1 knapsack problem, a set of items is given, each with a weight and a value. 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 the given limit and the total value is as large as possible.

Example

The following example explains the 0-1 knapsack problem:

Input:
Weights: 1 2 3 6 7 4 
Values: 10 20 25 40 60 70 
Max Weight Capacity: 7

Output:
Maximum value: 100

Here is an explanation of the above example:

Weights: 1 2 3 6 7 4
Values: 10 20 25 40 60 70
Max Weight Capacity: 7

We will select the weights with maximum weight as 7:
Weight = {1, 2, 3}, Value = {10, 20, 25} = 55
Weight = {1, 2, 4}, Value = {10, 20, 70} = 100
Weight = {1,6}, Value = {10, 40} = 50
.
.
Weight = {3,4}, Value = {25, 70} = 95

=> Maximum value = 100, Weights = {1, 2, 4}

Here is a list of approaches to solve the 0-1 knapsack problem in C++ with step-wise explanation and complete example codes.

Solve 0-1 Knapsack Problem Using Recursion

In this approach, to solve the 0-1 knapsack problem, we have used a recursive solution where we decide whether to include or exclude the current item or not at each step. If we are including the item in the knapsack, then we reduce the remaining capacity and move to the next item. If we are excluding the item, then we simply move to the next item without reducing the capacity value.

  • We have created a function ksRecur() that accepts the weight, value, maximum capacity, and number of elements in the argument.
  • In this function, we have defined three cases, i.e. the base case, when an item is included, and when the item is excluded. The base case returns 0 when there is no item left or capacity becomes 0.
  • If the weight is less than the maximum capacity then we include its value and recursively call the ksRecur() function with the remaining elements by reducing the capacity.
  • Similarly, if the value is excluded, then we recursively call the ksRecur() function without reducing the capacity.
  • Then, we return the maximum value out of the include and exclude value.

Example

In this example, we have used the above-mentioned steps to solve the 0-1 knapsack problem in C++ using recursion.

#include <iostream>
using namespace std;

int ksRecur(int weights[], int values[], int n, int capacity) {
    if (n == 0 || capacity == 0) 
        return 0;  // Base case

    // Exclude the item
    int exclude = ksRecur(weights, values, n - 1, capacity);
    
    // Include the item (if it fits in the knapsack)
    int include = 0;
    if (weights[n - 1] <= capacity)
        include = values[n - 1] + ksRecur(weights, values, n - 1, capacity - weights[n - 1]);

    return max(include, exclude);  // Return the maximum of both cases
}

int main() {
    int weights[] = {1, 2, 3, 6, 7, 4};
    cout << "Weights: ";
    for (int i = 0; i < 6; i++) 
        cout << weights[i] << " ";
    int values[] = {10, 20, 25, 40, 60, 70};
    cout << "\nValues: ";
    for (int i = 0; i < 6; i++) 
        cout << values[i] << " ";
    int capacity = 7;
    cout << "\nMax Weight Capacity: " << capacity << endl;
    int n = 6;
    cout << "Maximum value: " << ksRecur(weights, values, n, capacity) << endl;
    return 0;
}

The output of the above code is:

Weights: 1 2 3 6 7 4 
Values: 10 20 25 40 60 70 
Max Weight Capacity: 7
Maximum value: 100

Solve 0-1 Knapsack Problem Using Memoization

The following approach uses recursion with memoization. We have used a 2D vector dp to avoid the redundant calculation. It stores the results in this vector and the results are used again when needed.

  • It is similar to the previous approach, except we have added a 2D vector as memoization.
  • First, we check if the result is already present in this 2D vector or not. If the result is already present, then we use the value and if the result is not present, then we calculate the result and store it for future use.

Example

The following example implements the above-mentioned steps to implement the 0-1 knapsack problem using memoization.

#include <iostream>
#include <vector>
using namespace std;

int ksMemo(int weights[], int values[], int n, int capacity, vector<vector<int>> &dp) {
    if (n == 0 || capacity == 0) 
        return 0;  // Base case

    if (dp[n][capacity] != -1) return dp[n][capacity];  // Check if result is already computed

    // Exclude the item
    int exclude = ksMemo(weights, values, n - 1, capacity, dp);

    // Include the item (if it fits in the knapsack)
    int include = 0;
    if (weights[n - 1] <= capacity)
        include = values[n - 1] + ksMemo(weights, values, n - 1, capacity - weights[n - 1], dp);

    dp[n][capacity] = max(include, exclude);  // Store the result
    return dp[n][capacity];
}

int main() {
    int weights[] = {1, 2, 3, 6, 7, 4};
    cout << "Weights: ";
    for (int i = 0; i < 6; i++) 
        cout << weights[i] << " ";
    int values[] = {10, 20, 25, 40, 60, 70};
    cout << "\nValues: ";
    for (int i = 0; i < 6; i++) 
        cout << values[i] << " ";
    int capacity = 7;
    cout << "\nMax Weight Capacity: " << capacity << endl;
    int n = 6;
    vector<vector<int>> dp(n + 1, vector<int>(capacity + 1, -1));
    cout << "Maximum value: " << ksMemo(weights, values, n, capacity, dp) << endl;
    return 0;
}

The output of the above code is:

Weights: 1 2 3 6 7 4 
Values: 10 20 25 40 60 70 
Max Weight Capacity: 7
Maximum value: 100

Solve 0-1 Knapsack Problem Using Bottom-Up or Tabulation

To solve the 0-1 Knapsack problem, we have used a 2D DP table. In this table, we fill the table based on the earlier computed results iteratively. This approach uses the concepts of Dynamic Programming.

  • We have defined a ksDpTable() function that accepts weight, values, maximum capacity, and number of items as arguments.
  • In this function, first, we have created a DP table of (n+1) rows and (capacity+1) columns. Initially, this table is filled with 0s. It will store the maximum value.
  • The outer for loop iterates over all elements n, while the inner loop checks if the weight value is less than the maximum capacity.
  • If the item is excluded, then we store the previous value and move on to the next element.
  • If the element is included, then we update the current maximum weight in the table. Then the result is returned after the loop ends as dp[n][capacity].

Example

Here is an example of a 0-1 knapsack problem using the tabulation method.

#include <iostream>
#include <vector>
using namespace std;

int ksDpTable(int weights[], int values[], int n, int capacity) {
    vector<vector<int>> dp(n + 1, vector<int>(capacity + 1, 0));

    for (int i = 1; i <= n; ++i) {
        for (int w = 1; w <= capacity; ++w) {
            // If the item is not included
            dp[i][w] = dp[i - 1][w];

            // If the item is included
            if (weights[i - 1] <= w)
                dp[i][w] = max(dp[i][w], values[i - 1] + dp[i - 1][w - weights[i - 1]]);
        }
    }

    return dp[n][capacity];
}

int main() {
    int weights[] = {1, 2, 3, 6, 7, 4};
    cout << "Weights: ";
    for (int i = 0; i < 6; i++) 
        cout << weights[i] << " ";
    int values[] = {10, 20, 25, 40, 60, 70};
    cout << "\nValues: ";
    for (int i = 0; i < 6; i++) 
        cout << values[i] << " ";
    int capacity = 7;
    cout << "\nMax Weight Capacity: " << capacity << endl;
    int n = 6;
    cout << "Maximum value: " << ksDpTable(weights, values, n, capacity) << endl;
    return 0;
}

The output of the above code is:

Weights: 1 2 3 6 7 4 
Values: 10 20 25 40 60 70 
Max Weight Capacity: 7
Maximum value: 100

Solve 0-1 Knapsack Problem Using Space Optimized Approach

In this approach, we will use a single 1D array instead of a 2D table to store the results. Just like the previous approach where we had used a 2D table, here also, we will iteratively fill the array and maintain just the previous value of weight. This approach also follows the same approach as a 2D table, except we will be using a 1D array.

Example

This example demonstrates the use of a single-dimensional array to solve the 0-1 knapsack problem.

#include <iostream>
#include <vector>
using namespace std;

int ksOpt(int weights[], int values[], int n, int capacity) {
    vector<int> dp(capacity + 1, 0);

    for (int i = 0; i < n; ++i) {
        for (int w = capacity; w >= weights[i]; --w) {
            dp[w] = max(dp[w], values[i] + dp[w - weights[i]]);
        }
    }

    return dp[capacity];
}

int main() {
    int weights[] = {1, 2, 3, 6, 7, 4};
    cout << "Weights: ";
    for (int i = 0; i < 6; i++) 
        cout << weights[i] << " ";
    int values[] = {10, 20, 25, 40, 60, 70};
    cout << "\nValues: ";
    for (int i = 0; i < 6; i++) 
        cout << values[i] << " ";
    int capacity = 7;
    cout << "\nMax Weight Capacity: " << capacity << endl;
    int n = 6;
    cout << "Maximum value: " << ksOpt(weights, values, n, capacity) << endl;
    return 0;
}

The output of the above code is:

Weights: 1 2 3 6 7 4 
Values: 10 20 25 40 60 70 
Max Weight Capacity: 7
Maximum value: 100

Comparison of Approaches

Here is a comparison of the time and space complexity of all the above approaches.

Approach Time Complexity Space Complexity
Recursion O(2^n) O(n)
Memoization O(n*w) O(n*w)
Bottom-Up or Tabulation O(n*w) O(n*w)
Space Optimized Approach O(n*w) O(w)
Updated on: 2025-04-29T15:35:40+05:30

6K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started