0/1 Knapsack Problem (original) (raw)

Given two arrays, **val[] and **wt[], where each element represents the value and weight of an item respectively, also given an integer **W representing the maximum capacity of the knapsack (the total weight it can hold).Put the items into the knapsack such that the sum of values associated with them is the maximum possible, without exceeding the capacity W.

**Note: We can either include an item completely or exclude it entirely - we cannot include a fraction of an item.

**Examples:

**Input: W = 4, val[] = [1, 2, 3], wt[] = [4, 5, 1]
**Output: 3
**Explanation: There are two items with weight less than or equal to 4. If we select the item with weight 4, the possible value is 1, and if we select the item with weight 1, the possible value is 3. Hence, the maximum possible value is 3. We cannot put both items with weights 4 and 1 together because the capacity of the bag is 4.

**Input: W = 3, val[] = [1, 2, 3], wt[] = [4, 5, 6]
**Output: 0
**Explanation: All the item weights are greater than the knapsack capacity.

Table of Content

[Naive Approach] Using Recursion - O(2^n) Time and O(n) Space

The idea is to use recursion to explore all possible combinations of items. For each item, there are two choices: either include the item in the knapsack or skip it, depending on whether its weight allows it to fit within the remaining capacity.

For every item, compute the maximum value obtained from these two choices and return the larger one as the result.

71972263

C++ `

//Driver Code Starts #include using namespace std;

//Driver Code Ends

// Returns the maximum value that // can be put in a knapsack of capacity W int knapsackRec(int W, vector &val, vector &wt, int n) {

// Base Case
if (n == 0 || W == 0)
    return 0;

int pick = 0;

// Pick nth item if it does not exceed the capacity of knapsack
if (wt[n - 1] <= W)
    pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1);

// Don't pick the nth item
int notPick = knapsackRec(W, val, wt, n - 1);
 
return max(pick, notPick);

}

int knapsack(int W, vector &val, vector &wt) { int n = val.size(); return knapsackRec(W, val, wt, n); }

int main() {

//Driver Code Starts vector val = {1, 2, 3}; vector wt = {4, 5, 1}; int W = 4;

cout << knapsack(W, val, wt) << endl;
return 0;

} //Driver Code Ends

Java

class GfG {

// Returns the maximum value that
// can be put in a knapsack of capacity W
static int knapsackRec(int W, int[] val, int[] wt, int n) {

    // Base Case
    if (n == 0 || W == 0)
        return 0;

    int pick = 0;

    // Pick nth item if it does not exceed the capacity of knapsack
    if (wt[n - 1] <= W)
        pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1);
    
    // Don't pick the nth item
    int notPick = knapsackRec(W, val, wt, n - 1);
     
    return Math.max(pick, notPick);
}

static int knapsack(int W, int[] val, int[] wt) {
    int n = val.length;
    return knapsackRec(W, val, wt, n);
}


public static void main(String[] args) {

//Driver Code Starts int[] val = {1, 2, 3}; int[] wt = {4, 5, 1}; int W = 4;

    System.out.println(knapsack(W, val, wt));
}

}

//Driver Code Ends

Python

Returns the maximum value that

can be put in a knapsack of capacity W

def knapsackRec(W, val, wt, n):

# Base Case
if n == 0 or W == 0:
    return 0

pick = 0

# Pick nth item if it does not exceed the capacity of knapsack
if wt[n - 1] <= W:
    pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1)

# Don't pick the nth item
notPick = knapsackRec(W, val, wt, n - 1)
 
return max(pick, notPick)

def knapsack(W, val, wt): n = len(val) return knapsackRec(W, val, wt, n)

if name == "main": //Driver Code Starts val = [1, 2, 3] wt = [4, 5, 1] W = 4

print(knapsack(W, val, wt))

//Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

// Returns the maximum value that
// can be put in a knapsack of capacity W
static int knapsackRec(int W, int[] val, int[] wt, int n) {

    // Base Case
    if (n == 0 || W == 0)
        return 0;

    int pick = 0;

    // Pick nth item if it does not exceed the capacity of knapsack
    if (wt[n - 1] <= W)
        pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1);
    
    // Don't pick the nth item
    int notPick = knapsackRec(W, val, wt, n - 1);
     
    return Math.Max(pick, notPick);
}

static int knapsack(int W, int[] val, int[] wt) {
    int n = val.Length;
    return knapsackRec(W, val, wt, n);
}

//Driver Code Starts static void Main() { int[] val = { 1, 2, 3 }; int[] wt = { 4, 5, 1 }; int W = 4;

    Console.WriteLine(knapsack(W, val, wt));
}

}

//Driver Code Ends

JavaScript

// Returns the maximum value that // can be put in a knapsack of capacity W function knapsackRec(W, val, wt, n) {

// Base Case
if (n === 0 || W === 0)
    return 0;

let pick = 0;

// Pick nth item if it does not exceed the capacity of knapsack
if (wt[n - 1] <= W)
    pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1);

// Don't pick the nth item
let notPick = knapsackRec(W, val, wt, n - 1);
 
return Math.max(pick, notPick);

}

function knapsack(W, val, wt) { let n = val.length; return knapsackRec(W, val, wt, n); }

// Driver Code //Driver Code Starts let val = [1, 2, 3]; let wt = [4, 5, 1]; let W = 4;

console.log(knapsack(W, val, wt));

//Driver Code Ends

`

[Better Approach - 1] Using Top-Down DP (Memoization)- O(n x W) Time and O(n x W) Space

group_3361

**Note: The above function using recursion computes the same subproblems again and again. See the following recursion tree, K(1, 1) is being evaluated twice. As there are repetitions of the same subproblem again and again we can implement the following idea to solve the problem.

If we get a subproblem the first time, we can solve this problem by creating a 2-D array that can store a particular state. Now if we come across the same state again instead of calculating it i again we can directly return its result stored in the table in constant time.

C++ `

//Driver Code Starts #include using namespace std;

//Driver Code Ends

// Returns the maximum value that // can be put in a knapsack of capacity W int knapsackRec(int W, vector &val, vector &wt, int n, vector<vector> &memo) {

// Base Case
if (n == 0 || W == 0)
    return 0;

// Check if we have previously calculated the same subproblem
if(memo[n][W] != -1)
    return memo[n][W];

int pick = 0;

// Pick nth item if it does not exceed the capacity of knapsack
if (wt[n - 1] <= W)
    pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1, memo);

// Don't pick the nth item
int notPick = knapsackRec(W, val, wt, n - 1, memo);

// Store the result in memo[n][W] and return it
return memo[n][W] = max(pick, notPick);

}

int knapsack(int W, vector &val, vector &wt) { int n = val.size();

// Memoization table to store the results
vector<vector<int>> memo(n + 1, vector<int>(W + 1, -1));

return knapsackRec(W, val, wt, n, memo);

}

int main() {

//Driver Code Starts vector val = {1, 2, 3}; vector wt = {4, 5, 1}; int W = 4;

cout << knapsack(W, val, wt) << endl;
return 0;

} //Driver Code Ends

Java

class GfG {

// Returns the maximum value that
// can be put in a knapsack of capacity W
static int knapsackRec(int W, int[] val, int[] wt, int n, int[][] memo) {

    // Base Case
    if (n == 0 || W == 0)
        return 0;

    // Check if we have previously calculated the same subproblem
    if (memo[n][W] != -1)
        return memo[n][W];

    int pick = 0;

    // Pick nth item if it does not exceed the capacity of knapsack
    if (wt[n - 1] <= W)
        pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1, memo);

    // Don't pick the nth item
    int notPick = knapsackRec(W, val, wt, n - 1, memo);

    // Store the result in memo[n][W] and return it
    return memo[n][W] = Math.max(pick, notPick);
}

static int knapsack(int W, int[] val, int[] wt) {
    int n = val.length;

    // Memoization table to store the results
    int[][] memo = new int[n + 1][W + 1];

    // Initialize memoization table with -1
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= W; j++)
            memo[i][j] = -1;
    }

    return knapsackRec(W, val, wt, n, memo);
}


public static void main(String[] args) {

//Driver Code Starts int[] val = { 1, 2, 3 }; int[] wt = { 4, 5, 1 }; int W = 4;

    System.out.println(knapsack(W, val, wt));
}

}

//Driver Code Ends

Python

Returns the maximum value that

can be put in a knapsack of capacity W

def knapsackRec(W, val, wt, n, memo):

# Base Case
if n == 0 or W == 0:
    return 0

# Check if we have previously calculated the same subproblem
if memo[n][W] != -1:
    return memo[n][W]

pick = 0

# Pick nth item if it does not exceed the capacity of knapsack
if wt[n - 1] <= W:
    pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1, memo)

# Don't pick the nth item
notPick = knapsackRec(W, val, wt, n - 1, memo)

# Store the result in memo[n][W] and return it
memo[n][W] = max(pick, notPick)
return memo[n][W]

def knapsack(W, val, wt): n = len(val)

# Memoization table to store the results
memo = [[-1] * (W + 1) for _ in range(n + 1)]

return knapsackRec(W, val, wt, n, memo)

if name == "main": #Driver Code Starts val = [1, 2, 3] wt = [4, 5, 1] W = 4

print(knapsack(W, val, wt))

#Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

// Returns the maximum value that
// can be put in a knapsack of capacity W
static int knapsackRec(int W, int[] val, int[] wt, int n, ref int[,] memo) {
    
    // Base Case
    if (n == 0 || W == 0)
        return 0;

    // Check if we have previously calculated the same subproblem
    if (memo[n, W] != -1)
        return memo[n, W];

    int pick = 0;

    // Pick nth item if it does not exceed the capacity of knapsack
    if (wt[n - 1] <= W)
        pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1, ref memo);

    // Don't pick the nth item
    int notPick = knapsackRec(W, val, wt, n - 1, ref memo);

    // Store the result in memo[n, W] and return it
    return memo[n, W] = Math.Max(pick, notPick);
}

static int knapsack(int W, int[] val, int[] wt) {
    int n = val.Length;

    // Memoization table to store the results
    int[,] memo = new int[n + 1, W + 1];

    // Initialize memo table with -1
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <= W; j++)
        {
            memo[i, j] = -1;
        }
    }

    return knapsackRec(W, val, wt, n, ref memo);
}

//Driver Code Starts static void Main() { int[] val = { 1, 2, 3 }; int[] wt = { 4, 5, 1 }; int W = 4;

    Console.WriteLine(knapsack(W, val, wt));
}

}

//Driver Code Ends

JavaScript

// Returns the maximum value that // can be put in a knapsack of capacity W function knapsackRec(W, val, wt, n, memo) {

// Base Case
if (n === 0 || W === 0)
    return 0;

// Check if we have previously calculated the same subproblem
if (memo[n][W] !== -1)
    return memo[n][W];

let pick = 0;

// Pick nth item if it does not exceed the capacity of knapsack
if (wt[n - 1] <= W)
    pick = val[n - 1] + knapsackRec(W - wt[n - 1], val, wt, n - 1, memo);

// Don't pick the nth item
let notPick = knapsackRec(W, val, wt, n - 1, memo);

// Store the result in memo[n][W] and return it
memo[n][W] = Math.max(pick, notPick);
return memo[n][W];

}

function knapsack(W, val, wt) { const n = val.length;

// Memoization table to store the results
const memo = Array.from({ length: n + 1 }, () => Array(W + 1).fill(-1));

return knapsackRec(W, val, wt, n, memo);

}

// Driver Code //Driver Code Starts const val = [1, 2, 3]; const wt = [4, 5, 1]; const W = 4;

console.log(knapsack(W, val, wt));

//Driver Code Ends

`

[Better Approach - 2] Using Bottom-Up DP (Tabulation) - O(n x W) Time and O(n x W) Space

In the recursive solution, two parameters change: the number of items and the knapsack capacity. These parameters range from 0 to n and 0 to W, respectively. Therefore, we create a 2D array dp[][] of size (n+1) × (W+1), where dp[i][j] stores the maximum value that can be obtained using the first i items with a knapsack capacity of j. The table is first initialized for the base cases when i = 0 or j = 0. After that, the remaining entries are filled using the recursive formula.

For each item i and knapsack capacity j, we decide whether to pick the item or not.

//Driver Code Starts #include using namespace std;

//Driver Code Ends

int knapsack(int W, vector &val, vector &wt) { int n = wt.size(); vector<vector> dp(n + 1, vector(W + 1));

// Build table dp[][] in bottom-up manner
for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= W; j++) {
        
        // If there is no item or the knapsack's capacity is 0
        if (i == 0 || j == 0)
            dp[i][j] = 0;
        else {
            int pick = 0;
            
            // Pick ith item if it does not exceed the capacity of knapsack
            if(wt[i - 1] <= j)
                pick = val[i - 1] + dp[i - 1][j - wt[i - 1]];
                
            // Don't pick the ith item
            int notPick = dp[i - 1][j];
            
            dp[i][j] = max(pick, notPick);
        }
    }
}
return dp[n][W];

}

int main() {

//Driver Code Starts vector val = {1, 2, 3}; vector wt = {4, 5, 1}; int W = 4;

cout << knapsack(W, val, wt) << endl;
return 0;

} //Driver Code Ends

Java

//Driver Code Starts class GfG {

//Driver Code Ends

static int knapsack(int W, int[] val, int[] wt) {
    int n = wt.length;
    int[][] dp = new int[n + 1][W + 1];

    // Build table dp[][] in bottom-up manner
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= W; j++) {

            // If there is no item or the knapsack's capacity is 0
            if (i == 0 || j == 0)
                dp[i][j] = 0;
            else {
                int pick = 0;

                // Pick ith item if it does not exceed the capacity of knapsack
                if (wt[i - 1] <= j)
                    pick = val[i - 1] + dp[i - 1][j - wt[i - 1]];

                // Don't pick the ith item
                int notPick = dp[i - 1][j];

                dp[i][j] = Math.max(pick, notPick);
            }
        }
    }
    return dp[n][W];
}

public static void main(String[] args) {

//Driver Code Starts int[] val = {1, 2, 3}; int[] wt = {4, 5, 1}; int W = 4;

    System.out.println(knapsack(W, val, wt));
}

}

//Driver Code Ends

Python

def knapsack(W, val, wt): n = len(wt) dp = [[0 for _ in range(W + 1)] for _ in range(n + 1)]

# Build table dp[][] in bottom-up manner
for i in range(n + 1):
    for j in range(W + 1):

        # If there is no item or the knapsack's capacity is 0
        if i == 0 or j == 0:
            dp[i][j] = 0
        else:
            pick = 0

            # Pick ith item if it does not exceed the capacity of knapsack
            if wt[i - 1] <= j:
                pick = val[i - 1] + dp[i - 1][j - wt[i - 1]]

            # Don't pick the ith item
            notPick = dp[i - 1][j]

            dp[i][j] = max(pick, notPick)

return dp[n][W]

if name == "main": #Driver Code Starts val = [1, 2, 3] wt = [4, 5, 1] W = 4

print(knapsack(W, val, wt))

#Driver Code Ends

C#

//Driver Code Starts using System; using System.Linq;

class GfG { //Driver Code Ends

static int knapsack(int W, int[] val, int[] wt)
{
    int n = wt.Length;
    int[, ] dp = new int[n + 1, W + 1];

    // Build table dp[][] in bottom-up manner
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= W; j++) {

            // If there is no item or the knapsack's
            // capacity is 0
            if (i == 0 || j == 0)
                dp[i, j] = 0;
            else {
                int pick = 0;

                // Pick ith item if it does not exceed
                // the capacity of knapsack
                if (wt[i - 1] <= j)
                    pick = val[i - 1]
                           + dp[i - 1, j - wt[i - 1]];

                // Don't pick the ith item
                int notPick = dp[i - 1, j];

                dp[i, j] = Math.Max(pick, notPick);
            }
        }
    }
    return dp[n, W];
}

//Driver Code Starts

static void Main()
{
    int[] val = { 1, 2, 3 };
    int[] wt = { 4, 5, 1 };
    int W = 4;

    Console.WriteLine(knapsack(W, val, wt));
}

} //Driver Code Ends

JavaScript

function knapsack(W, val, wt) { let n = wt.length; let dp = Array.from({ length: n + 1 }, () => Array(W + 1).fill(0));

// Build table dp[][] in bottom-up manner
for (let i = 0; i <= n; i++) {
    for (let j = 0; j <= W; j++) {

        // If there is no item or the knapsack's capacity is 0
        if (i === 0 || j === 0)
            dp[i][j] = 0;
        else {
            let pick = 0;

            // Pick ith item if it does not exceed the capacity of knapsack
            if (wt[i - 1] <= j)
                pick = val[i - 1] + dp[i - 1][j - wt[i - 1]];

            // Don't pick the ith item
            let notPick = dp[i - 1][j];

            dp[i][j] = Math.max(pick, notPick);
        }
    }
}
return dp[n][W];

}

// Driver code

let val = [1, 2, 3]; //Driver Code Starts let wt = [4, 5, 1]; let W = 4;

console.log(knapsack(W, val, wt));

//Driver Code Ends

`

[Expected Approach] Using Bottom-Up DP (Space-Optimized) - O(n x W) Time and O(W) Space

To compute the current row of the dp[] array, we only need values from the previous row. Therefore, instead of maintaining the entire 2D dp table, we can optimize space by using just a single 1D array. By traversing the array from right to left, we ensure that previously computed values are not overwritten before they are used.

C++ `

//Driver Code Starts #include using namespace std;

//Driver Code Ends

int knapsack(int W, vector &val, vector &wt) {

// Initializing dp vector
vector<int> dp(W + 1, 0);

// Taking first i elements
for (int i = 1; i <= wt.size(); i++) {
    
    // Starting from back, so that we also have data of
    // previous computation of i-1 items
    for (int j = W; j >= wt[i - 1]; j--) {
        dp[j] = max(dp[j], dp[j - wt[i - 1]] + val[i - 1]);
    }
}
return dp[W];

}

int main() {

//Driver Code Starts vector val = {1, 2, 3}; vector wt = {4, 5, 1}; int W = 4;

cout << knapsack(W, val, wt) << endl;
return 0;

} //Driver Code Ends

Java

//Driver Code Starts class GfG { //Driver Code Ends

static int knapsack(int W, int[] val, int[] wt) {
    
    // Initializing dp array
    int[] dp = new int[W + 1];
    
    // Taking first i elements
    for (int i = 1; i <= wt.length; i++) {
        
        // Starting from back, so that we also have data of
        // previous computation of i-1 items
        for (int j = W; j >= wt[i - 1]; j--) {
            dp[j] = Math.max(dp[j], dp[j - wt[i - 1]] + val[i - 1]);
        }
    }
    return dp[W];
}

//Driver Code Starts public static void main(String[] args) { int[] val = {1, 2, 3}; int[] wt = {4, 5, 1}; int W = 4;

    System.out.println(knapsack(W, val, wt));
}

}

//Driver Code Ends

Python

def knapsack(W, val, wt):

# Initializing dp list
dp = [0] * (W + 1)

# Taking first i elements
for i in range(1, len(wt) + 1):
    
    # Starting from back, so that we also have data of
    # previous computation of i-1 items
    for j in range(W, wt[i - 1] - 1, -1):
        dp[j] = max(dp[j], dp[j - wt[i - 1]] + val[i - 1])

return dp[W]

if name == "main": #Driver Code Starts val = [1, 2, 3] wt = [4, 5, 1] W = 4

print(knapsack(W, val, wt))

#Driver Code Ends

C#

//Driver Code Starts using System;

class GfG { //Driver Code Ends

static int knapsack(int W, int[] val, int[] wt) {
    
    // Initializing dp array
    int[] dp = new int[W + 1];

    // Taking first i elements
    for (int i = 1; i <= wt.Length; i++) {
        
        // Starting from back, so that we also have data of
        // previous computation of i-1 items
        for (int j = W; j >= wt[i - 1]; j--) {
            dp[j] = Math.Max(dp[j], dp[j - wt[i - 1]] + val[i - 1]);
        }
    }
    return dp[W];
}

//Driver Code Starts static void Main() { int[] val = { 1, 2, 3 }; int[] wt = { 4, 5, 1 }; int W = 4;

    Console.WriteLine(knapsack(W, val, wt));
}

}

//Driver Code Ends

JavaScript

function knapsack(W, val, wt) {

// Initializing dp array
let dp = new Array(W + 1).fill(0);

// Taking first i elements
for (let i = 1; i <= wt.length; i++) {
    
    // Starting from back, so that we also have data of
    // previous computation of i-1 items
    for (let j = W; j >= wt[i - 1]; j--) {
        dp[j] = Math.max(dp[j], dp[j - wt[i - 1]] + val[i - 1]);
    }
}
return dp[W];

}

// Driver Code

//Driver Code Starts let val = [1, 2, 3]; let wt = [4, 5, 1]; let W = 4;

console.log(knapsack(W, val, wt));

//Driver Code Ends

`