Python Program for 0-1 Knapsack Problem

The 0-1 Knapsack Problem is a classic optimization problem where you have a knapsack with limited capacity and items with specific weights and values. The goal is to select items that maximize value without exceeding the weight limit, where each item can only be taken once (0 or 1).

Problem Types

There are three main variants of the knapsack problem −

  • 0-1 Knapsack: Each item can either be selected or not (0 or 1)
  • Fractional Knapsack: Items can be broken into fractions
  • Unbounded Knapsack: Items can be selected multiple times

Problem Statement

Given n items with weights w[i] and values v[i], fill a knapsack of capacity W to maximize total value without exceeding the weight limit. Each item can only be chosen once.

Recursive Solution

The recursive approach explores all possible combinations by deciding whether to include or exclude each item ?

def knapsack_recursive(W, weights, values, n):
    # Base case: no items left or no capacity
    if n == 0 or W == 0:
        return 0
    
    # If current item's weight exceeds capacity, skip it
    if weights[n-1] > W:
        return knapsack_recursive(W, weights, values, n-1)
    
    # Return maximum of including or excluding current item
    include = values[n-1] + knapsack_recursive(W - weights[n-1], weights, values, n-1)
    exclude = knapsack_recursive(W, weights, values, n-1)
    
    return max(include, exclude)

# Test data
values = [50, 100, 150, 200]
weights = [8, 16, 32, 40]
capacity = 64
n = len(values)

result = knapsack_recursive(capacity, weights, values, n)
print(f"Maximum value (Recursive): {result}")
Maximum value (Recursive): 350

Dynamic Programming Solution

The DP approach eliminates redundant calculations by storing subproblem results in a 2D table. This significantly improves efficiency ?

def knapsack_dp(W, weights, values, n):
    # Create DP table: dp[i][w] = max value with first i items and capacity w
    dp = [[0 for _ in range(W + 1)] for _ in range(n + 1)]
    
    # Fill the table bottom-up
    for i in range(1, n + 1):
        for w in range(1, W + 1):
            # If current item's weight exceeds capacity, skip it
            if weights[i-1] > w:
                dp[i][w] = dp[i-1][w]
            else:
                # Take maximum of including or excluding current item
                include = values[i-1] + dp[i-1][w - weights[i-1]]
                exclude = dp[i-1][w]
                dp[i][w] = max(include, exclude)
    
    return dp[n][W]

# Test data
values = [50, 100, 150, 200]
weights = [8, 16, 32, 40]
capacity = 64
n = len(values)

result = knapsack_dp(capacity, weights, values, n)
print(f"Maximum value (DP): {result}")
Maximum value (DP): 350

Finding Selected Items

To track which items were selected, we can backtrack through the DP table ?

def knapsack_with_items(W, weights, values, n):
    # Build DP table
    dp = [[0 for _ in range(W + 1)] for _ in range(n + 1)]
    
    for i in range(1, n + 1):
        for w in range(1, W + 1):
            if weights[i-1] > w:
                dp[i][w] = dp[i-1][w]
            else:
                include = values[i-1] + dp[i-1][w - weights[i-1]]
                exclude = dp[i-1][w]
                dp[i][w] = max(include, exclude)
    
    # Backtrack to find selected items
    selected_items = []
    w = W
    for i in range(n, 0, -1):
        if dp[i][w] != dp[i-1][w]:
            selected_items.append(i-1)  # Item index
            w -= weights[i-1]
    
    return dp[n][W], selected_items[::-1]

# Test data
values = [50, 100, 150, 200]
weights = [8, 16, 32, 40]
capacity = 64
n = len(values)

max_value, items = knapsack_with_items(capacity, weights, values, n)
print(f"Maximum value: {max_value}")
print(f"Selected items (indices): {items}")
print(f"Selected weights: {[weights[i] for i in items]}")
print(f"Selected values: {[values[i] for i in items]}")
Maximum value: 350
Selected items (indices): [0, 1, 2]
Selected weights: [8, 16, 32]
Selected values: [50, 100, 150]

Complexity Analysis

Approach Time Complexity Space Complexity
Recursive O(2^n) O(n)
Dynamic Programming O(n × W) O(n × W)

Applications

The 0-1 Knapsack problem has numerous real-world applications:

  • Resource Allocation: Budget planning and project selection
  • Cargo Loading: Maximizing value while respecting weight limits
  • Investment Planning: Portfolio optimization under constraints
  • Memory Management: Selecting programs to load in limited memory

Conclusion

The 0-1 Knapsack problem demonstrates the power of dynamic programming over naive recursion. While the recursive solution has exponential time complexity, the DP approach reduces it to O(n × W), making it practical for larger inputs.

Updated on: 2026-03-25T06:47:49+05:30

6K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements