Given the weights w and profits p of ‘N’ items, need to find a subset of these items which will give max profit with contstraint that their cumulative sum should not be greater than total knapsack capacity C.
Each item can only be selected only once and each item will be either taken (1) or skipped (0).
Example:
Items: {Apple, Orange, Banana, Melon}
Weights(w): {2, 3, 1, 4}
Profits(p): {4, 5, 3, 7}
Knapsack Capacity(C): 5
Answer: 10 - Banana + Melon with total weight 5
All other combinations with weight 5 or less has lesser profits.
Code :
def solve_knapsack_recursion(profits, weights, capacity):
item_index = 0
return solve_knapsack_recursion_util(profits, weights, capacity, item_index)
def solve_knapsack_recursion_util(profits, weights, capacity, item_index):
if (capacity <= 0 or item_index >= len(profits)):
return 0
profit1 = 0
if (weights[item_index] <= capacity): # can be included
profit1 = profits[item_index] + solve_knapsack_recursion_util(profits, weights,
capacity-weights[item_index], item_index+1)
profit2 = solve_knapsack_recursion_util(profits, weights, capacity, item_index+1)
return max(profit1, profit2)
print("Recursive Method :")
print(solve_knapsack_recursion([1, 6, 10, 16], [1, 2, 3, 5], 7))
print(solve_knapsack_recursion([1, 6, 10, 16], [1, 2, 3, 5], 6))
Output:
Recursive Method :
22
17
Complexity:
Identifying the problem as DP:
c:4, i:3
is repeating and hence can be solved using memoization.Code:
def solve_knapsack_dp_memoization(profits, weights, capacity):
memory = [[None]*(capacity+1) for i in range(len(profits))]
item_index = 0
return solve_knapsack_dp_memoization_util(profits, weights, capacity, item_index, memory)
def solve_knapsack_dp_memoization_util(profits, weights, capacity, item_index, memory):
if (capacity <= 0 or item_index >= len(profits)):
return 0
if(memory[item_index][capacity]):
return memory[item_index][capacity]
profit1 = 0
if (weights[item_index] <= capacity): # can be included
profit1 = profits[item_index] + solve_knapsack_dp_memoization_util(profits, weights,
capacity-weights[item_index], item_index+1, memory)
profit2 = solve_knapsack_dp_memoization_util(profits, weights, capacity, item_index+1, memory)
memory[item_index][capacity] = max(profit1, profit2)
return memory[item_index][capacity]
print("\nDP -> Recursion + Memoization Method :")
print(solve_knapsack_dp_memoization([1, 6, 10, 16], [1, 2, 3, 5], 7))
print(solve_knapsack_dp_memoization([1, 6, 10, 16], [1, 2, 3, 5], 6))
Output:
DP -> Recursion + Memoization Method :
22
17
Complexity:
Table Filling Formula:
table[i][c] = max(table[i-1][c], profits[i] + table[i-1][c-weights[i])
Tabulation:
Final Table:
Code:
def solve_knapsack_dp_tabulation(profits, weights, capacity):
table = [[0]*(capacity+1) for i in range(len(profits))]
# When capacity is zero then, none of the item can be selected
for i in range(len(profits)):
table[i][0] = 0
# If we consider only first weight, we will take it if its weight is less than capacity
for c in range(capacity+1):
if(weights[0] <= c):
table[0][c] = profits[0]
# Now consider rest by taking max of 1) current item can be included 2) current item is excluded
for i in range(1, len(profits)):
for c in range(1, capacity+1):
if(weights[i] <= c):
table[i][c] = max(table[i-1][c], profits[i] + table[i-1][c-weights[i]])
else:
table[i][c] = table[i-1][c]
return table[i][c]
print("\nDP -> Iteration + Tabulation Method :")
print(solve_knapsack_dp_tabulation([1, 6, 10, 16], [1, 2, 3, 5], 7))
print(solve_knapsack_dp_tabulation([1, 6, 10, 16], [1, 2, 3, 5], 6))
Output:
DP -> Iteration + Tabulation Method :
22
17
Complexity:
Code:
def solve_knapsack_dp_tabulation(profits, weights, capacity):
table = [[-1]*(capacity+1) for _ in range(len(profits))]
# When capacity is zero then, none of the item can be selected
for i in range(len(profits)):
table[i][0] = 0
# If we consider only first weight, we will take it if its weight is less than capacity
for c in range(capacity+1):
if(weights[0] <= c):
table[0][c] = profits[0]
# Now consider rest by taking max of 1) current item can be included 2) current item is excluded
for i in range(1, len(profits)):
for c in range(1, capacity+1):
if(weights[i] <= c):
table[i][c] = max(table[i-1][c], profits[i] + table[i-1][c-weights[i]])
else:
table[i][c] = table[i-1][c]
pick_selected_items(table, weights, profits)
return table[i][c]
def pick_selected_items(table, weights, profits):
i, c = len(table) - 1, len(table[0]) - 1
total_profit = table[i][c]
print("Selected items are : ")
while(total_profit > 0 and i-1 >= 0):
if(table[i][c] != table[i-1][c]):
print(f"item - {i+1} with weight : {weights[i]} and total_profit : {profits[i]}")
total_profit -= profits[i]
c -= weights[i]
i -= 1
if total_profit != 0:
print(f"item - {1} with weight : {weights[0]} and total_profit : {profits[0]}")
print("\nDP -> Iteration + Tabulation Method :")
print(solve_knapsack_dp_tabulation([1, 6, 10, 16], [1, 2, 3, 5], 7))
print(solve_knapsack_dp_tabulation([1, 6, 10, 16], [1, 2, 3, 5], 6))
Output:
DP -> Iteration + Tabulation Method :
Selected items are :
item - 4 with weight : 5 and total_profit : 16
item - 2 with weight : 2 and total_profit : 6
22
Selected items are :
item - 3 with weight : 3 and total_profit : 10
item - 2 with weight : 2 and total_profit : 6
item - 1 with weight : 1 and total_profit : 1
17
Code:
def solve_knapsack_dp_tabulation_optimized_space(profits, weights, capacity):
table = [0]*(capacity+1)
# If we consider only first weight, we will take it if its weight is less than capacity
for c in range(capacity+1):
if(weights[0] <= c):
table[c] = profits[0]
# Now consider rest by taking max of 1) current item can be included 2) current item is excluded
for i in range(1, len(profits)):
for c in range(capacity, -1, -1):
if(weights[i] <= c):
table[c] = max(table[c], profits[i] + table[c-weights[i]])
else:
table[c] = table[c]
return table[capacity]
print("\nDP -> Iteration + Tabulation - Optimized Space Method :")
print(solve_knapsack_dp_tabulation_optimized_space([1, 6, 10, 16], [1, 2, 3, 5], 7))
print(solve_knapsack_dp_tabulation_optimized_space([1, 6, 10, 16], [1, 2, 3, 5], 6))
Output:
DP -> Iteration + Tabulation - Optimized Space Method :
22
17
Complexity:
← Previous: Fibonacci Numbers Pattern
Next: Unbounded Knapsack Pattern →