C++ Program to Solve the 0-1 Knapsack Problem
Last Updated :
11 Jun, 2024
Prerequisite: Introduction to Knapsack Problem, its Types and How to solve them
The 0-1 Knapsack Problem is a classic problem in dynamic programming. For a given set of N items, each having a weight and a value, and a knapsack (a bag that can hold at most W weight inside it) with a maximum weight capacity W. The task is to determine the maximum sum of value of items that can be packed into the knapsack without exceeding its capacity. Unlike the Fractional Knapsack Problem, where you can take fractions of items, in the 0-1 Knapsack Problem, you can either take an item completely or leave it.
Example:
Input:
Number of Items (N): 4
Knapsack Capacity (W): 5
Item Weights: [1, 2, 4, 5]
Item Values: [5, 4, 8, 6]
Output:
13
Explanation: The optimal selection is to take the items with weights 1 and 4, giving a total value of 5 + 8 = 13.
This is the maximum value that can be achieved without exceeding the knapsack capacity of 5.
To learn more about the 0-1 Knapsack Problem refer: 0/1 Knapsack Problem
Method 1: Recursion Approach
The recursive approach explores all possible combinations of items by including or excluding each item at every step and calculating the total weight and value of all subsets (by considering only the subsets that have total weight less than W). Among all these subsets, pick the subset with maximum value. To implement this idea follow the below approach:
Approach:
- Base Case: If no items are left or the capacity is 0, return 0.
- Including the Nth item: Calculate the value if the Nth item is included, i.e., value of the Nth item plus the maximum value obtained from the remaining items and remaining weight.
- Excluding the Nth item: Calculate the maximum value obtained by the N-1 items and the original weight.
- Return the maximum of the above two cases.
- If the weight of the Nth item is greater than W, then the Nth item cannot be included and only Case 2 is possible.
The below program demonstrates the implementation of the above recursive approach:
C++
// C++ program for solving 0/1 Knapsack Problem using
// recursion
#include <iostream>
#include <vector>
using namespace std;
// Recursive function to solve 0/1 Knapsack problem
int knapsackRecursive(vector<int>& weight,
vector<int>& value, int W, int n)
{
// Base case: no items left or capacity is 0
if (n == 0 || W == 0)
return 0;
// If weight of the nth item is more than knapsack
// capacity W, it cannot be included
if (weight[n - 1] > W)
return knapsackRecursive(weight, value, W, n - 1);
// Return the maximum of two cases: (1) nth item
// included (2) not included
return max(value[n - 1]
+ knapsackRecursive(weight, value,
W - weight[n - 1],
n - 1),
knapsackRecursive(weight, value, W, n - 1));
}
int main()
{
// define a vector of weight
vector<int> weight = { 1, 2, 4, 5 };
// define a vector of value
vector<int> value = { 5, 4, 8, 6 };
// Knapsack capacity
int W = 5;
// call the recusrsive function and print the max value
// obtained
cout << "Maximum value = "
<< knapsackRecursive(weight, value, W,
weight.size())
<< endl;
return 0;
}
Time Complexity: O(2^N), due to the exponential number of subproblems generated.
Auxilliary Space: O(N), due to the recursion stack.
Method 2: Memoization Approach
For optimizing the recursive approach discussed earlier, memoization technique can be used that stores the results of already computed subproblems to avoid redundant computations and when the same inputs occur again it returns the stored result only. To implement this idea follow the below approach:
Approach:
- First, create a 2D array of size (N+1) x (W+1) and initialize it with -1 call it "memo table".
- Base Case: If no items are left or capacity is 0, return 0.
- Check the memo table for the inputs if the corresponding result is already computed, return it.
- Include the Nth item: calculate the value if the Nth item is included.
- Exclude the Nth item: calculate the maximum value if the Nth item is excluded.
- Store the result in the memo table and return it.
- If the weight of the Nth item is greater than W, then the Nth item cannot be included and only exclusion case is possible.
The below program demonstrates the implementation of the memorization approach:
C++
// C++ program for solving 0/1 Knapsack Problem using
// memoization technique
#include <iostream>
#include <vector>
using namespace std;
// Function to solve 0/1 Knapsack problem using Memoization
int knapsackMemoization(vector<int>& weight,
vector<int>& value, int W, int n,
vector<vector<int> >& memo)
{
// Base case: no items left or capacity is 0
if (n == 0 || W == 0)
return 0;
// Check if the result is already in the memo table
if (memo[n][W] != -1)
return memo[n][W];
// If weight of the nth item is more than knapsack
// capacity W, it cannot be included
if (weight[n - 1] > W) {
memo[n][W] = knapsackMemoization(weight, value, W,
n - 1, memo);
return memo[n][W];
}
// Return the maximum of two cases: (1) nth item
// included (2) not included
memo[n][W] = max(
value[n - 1]
+ knapsackMemoization(weight, value,
W - weight[n - 1], n - 1,
memo),
knapsackMemoization(weight, value, W, n - 1, memo));
return memo[n][W];
}
int main()
{
// define a vector of weight
vector<int> weight = { 1, 2, 4, 5 };
// define a vector of value
vector<int> value = { 5, 4, 8, 6 };
// Knapsack capacity
int W = 5;
int n = weight.size();
// declare a 2D array of size (N+1) x (W+1) callede memo
// initialized with -1
vector<vector<int> > memo(n + 1,
vector<int>(W + 1, -1));
// call the function and print the max value
// obtained
cout << "Maximum value = "
<< knapsackMemoization(weight, value, W, n, memo)
<< endl;
return 0;
}
Time Complexity: O(N * W), due to the memoization of previously calculated subproblems.
Auxilliary Space: O(N * W), for the dp array.
Method 3: Tabulation or Bottom-up Approach
The tabulation approach, also known as bottom-up approach solves the problem iteratively by filling up a table (2D array) in a bottom-up manner. It avoids the overhead of recursive calls and is generally more space-efficient.
Approach:
- Create a 2D array dp of size (N+1) x (W+1) initialized to 0.
- Iterate through each item and each capacity from 0 to W.
- For each item and capacity, decide whether to include or exclude the item if the item can be included, update the dp table with the maximum value by including or excluding the item.
- The value in dp[N][W] will be the maximum value for the given knapsack capacity.
The below program demonstrates the implementation of the tabulation or bottom-up approach:
C++
// C++ program for solving 0/1 Knapsack Problem using
// tabulation or bottom-up approach
#include <iostream>
#include <vector>
using namespace std;
// Function to solve 0/1 Knapsack problem using Bottom-up
// approach
int knapsackBottomUp(vector<int>& weight,
vector<int>& value, int W)
{
int N = weight.size();
// Create a 2D vector to store the maximum value that
// can be obtained dp[i][w] represents the maximum value
// that can be obtained with the first i items and
// capacity w
vector<vector<int> > dp(N + 1, vector<int>(W + 1, 0));
// Iterate over each item
for (int i = 1; i <= N; ++i) {
// Iterate over each capacity from 1 to W
for (int w = 1; w <= W; ++w) {
// Check if the weight of the current item is
// less than or equal to the current capacity
if (weight[i - 1] <= w) {
// Max value by including the current item
// or excluding it
dp[i][w] = max(dp[i - 1][w],
dp[i - 1][w - weight[i - 1]]
+ value[i - 1]);
}
else {
// If current item's weight is more than the
// current capacity, exclude it
dp[i][w] = dp[i - 1][w];
}
}
}
// Return the maximum value that can be obtained with
// the given capacity W
return dp[N][W];
}
int main()
{
// Define a vector of weights
vector<int> weight = { 1, 2, 4, 5 };
// Define a vector of values
vector<int> value = { 5, 4, 8, 6 };
// Knapsack capacity
int W = 5;
// Call the function and print the maximum value
// obtained
cout << "Maximum value = "
<< knapsackBottomUp(weight, value, W) << endl;
return 0;
}
Time Complexity: O(N * W) due to the nested loops iterating over all items and capacities.
Auxilliary Space: O(N * W)
Method 4: Space Optimized Approach
The space optimization approach reduces the space complexity of the tabulation approach by using only a single row to store intermediate results that is by using 1D array. This optimization is possible because we only need the current and previous states to compute the solution.
Approach:
- Create a 1D array dp of size (W+1) initialized to 0.
- For each item, iterate through all capacities from W to the item's weight.
- Update the DP array with the maximum value by including the item.
- The value at dp[W] is the maximum value for the given knapsack capacity.
The below program demonstrates the implementation of the space optimized approach:
C++
// C++ program for solving 0/1 Knapsack Problem using
// space optimized approach
#include <iostream>
#include <vector>
using namespace std;
// Function to solve 0/1 Knapsack problem with optimized
// space
int knapsackOptimized(vector<int>& weight,
vector<int>& value, int W)
{
int N = weight.size();
// Create a 1D vector to store the maximum value that
// can be obtained for each weight capacity
vector<int> dp(W + 1, 0);
// Iterate over each item
for (int i = 0; i < N; ++i) {
// Iterate over each capacity from W to the weight
// of the current item in reverse order
for (int w = W; w >= weight[i]; --w) {
// Update the dp array with the maximum value by
// including the current item
dp[w]
= max(dp[w], dp[w - weight[i]] + value[i]);
}
}
// Return the maximum value that can be obtained with
// the given capacity W
return dp[W];
}
int main()
{
// Define a vector of weights
vector<int> weight = { 1, 2, 4, 5 };
// Define a vector of values
vector<int> value = { 5, 4, 8, 6 };
// Knapsack capacity
int W = 5;
// Call the function and print the maximum value
// obtained
cout << "Maximum value = "
<< knapsackOptimized(weight, value, W) << endl;
return 0;
}
Time Complexity: O(N * W), due to the nested loops iterating over all items and capacities.
Auxiliary Space: O(W) for the dp array.
Similar Reads
C++ Program for the Fractional Knapsack Problem
Pre-requisite: Fractional Knapsack Problem Given two arrays weight[] and profit[] the weights and profit of N items, we need to put these items in a knapsack of capacity W to get the maximum total value in the knapsack.Note: Unlike 0/1 knapsack, you are allowed to break the item. Examples: Input: we
5 min read
C/C++ Dynamic Programming Programs
Dynamic programming refers to the programming paradigm in which the solution of the subproblems is memorized to avoid re-evaluation. Dynamic programming (DP) is the optimization of recursion that can only be applied to problems that have optimal substructure. In this article, we will discuss some of
2 min read
C++ Program to Count pairs with given sum
Given an array of integers, and a number 'sum', find the number of pairs of integers in the array whose sum is equal to 'sum'. Examples: Input : arr[] = {1, 5, 7, -1}, sum = 6 Output : 2 Pairs with sum 6 are (1, 5) and (7, -1) Input : arr[] = {1, 5, 7, -1, 5}, sum = 6 Output : 3 Pairs with sum 6 are
4 min read
C++ Program to Find all rectangles filled with 0
We have one 2D array, filled with zeros and ones. We have to find the starting point and ending point of all rectangles filled with 0. It is given that rectangles are separated and do not touch each other however they can touch the boundary of the array.A rectangle might contain only one element. Ex
5 min read
C++ Program For Linear Search
Linear search algorithm is the simplest searching algorithm that is used to find an element in the given collection. It simply compares the element to find with each element in the collection one by one till the matching element is found or there are no elements left to compare.In this article, we w
4 min read
C++ Program For Binary Search
Binary Search is a popular searching algorithm which is used for finding the position of any given element in a sorted array. It is a type of interval searching algorithm that keep dividing the number of elements to be search into half by considering only the part of the array where there is the pro
5 min read
C++ STL Practice Problems
Standard Template Library (STL) is a C++ library that provides the built-in implementation of commonly used data structures and algorithms. These components are designed as templates for generic coding. It is must to have knowledge of STL not only for development but also for competitive programming
2 min read
C++ Program for Minimum product subset of an array
Given an array a, we have to find the minimum product possible with the subset of elements present in the array. The minimum product can be a single element also. Examples:Â Input : a[] = { -1, -1, -2, 4, 3 } Output : -24 Explanation : Minimum product will be ( -2 * -1 * -1 * 4 * 3 ) = -24 Input : a
3 min read
Setting up a C++ Competitive Programming Environment
In this article, we will learn about how to setup all in one Competitive Programming Environment Operating System It is always recommended to use a Linux based OS. It is so because not only you will learn some better know-hows of the system but also will be able to get some pre-installed coding tool
5 min read
C++ Program for Counting sets of 1s and 0s in a binary matrix
Given a n à m binary matrix, count the number of sets where a set can be formed one or more same values in a row or column. Examples: Input: 1 0 1 0 1 0 Output: 8 Explanation: There are six one-element sets (three 1s and three 0s). There are two two- element sets, the first one consists of the first
2 min read