Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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.
