</br>
</br>
</br>
def knapsack(total, weights, values):
# initialize a list with size equal the total weight to obtain
dp = [0 for _ in range(total+1)]
# iterate over the different weights
for i in range(len(weights)):
# check if the current weight can improve the obtained value for different total weight we can achieve
for j in range(weights[i], total+1):
dp[j] = max(dp[j], dp[j-weights[i]] + values[i])
print(dp)
return(dp[-1])
knapsack(11, [6, 4, 8, 2], [30, 16, 14, 9])
[0, 0, 9, 9, 18, 18, 30, 30, 39, 39, 48, 48]
48
</br>
def knapsack_without_repetition(total, weights, values):
# initialize a two list with size equal the total weight to obtain
dp = [[0 for _ in range(total+1)] for _ in range(2)]
# iterate over the different weights
for i in range(len(weights)):
# check if the current weight can improve the obtained value for different total weight we can achieve
for j in range(weights[i], total+1):
# using two different list protects from using twice the same weight
dp[1][j] = max(dp[0][j], dp[0][j-weights[i]] + values[i]) # the value is stored in the second list but initiale values are taken from the first list
# it is just at the end of this weight turn that we copy the second list in the first one
dp[0] = [value for value in dp[1]]
return(dp[1][-1])
</br>
def knapsack_fractional_without_repetition(total, weights, values):
# Sort by ratios value/weight
ratios = {i: values[i]/weights[i] for i in range(len(weights))}
ratios = {k: v for k, v in sorted(ratios.items(), key=lambda item: -item[1])}
# Take maximum amount of elements with best ratios
total_value, remaining_space = 0, total
for k, v in ratios.items():
total_value += min(remaining_space, weights[k]) * v
remaining_space -= min(remaining_space, weights[k])
if remaining_space==0:
return(total_value)
return(total_value)
knapsack_fractional_without_repetition(10, [6, 4, 3, 2], [30, 16, 14, 9])