Skip to content

Commit e073d03

Browse files
committed
add knapsack in py
1 parent 9b07184 commit e073d03

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

Dynamic Programming/knapsack.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
'''
2+
You're given an array of arrays where each subarray holds two integer values and represents an item;
3+
the first integer is the item's value, and the second integer is the item's weight.
4+
You're also given an integer representing the maximum capacity of a knapsack that you have.
5+
6+
Your goal is to fit items in your knapsack without having the sum of their weights exceed the knapsack's
7+
capacity, all the while maximizing their combined value. Note that you only have one of each item at your disposal.
8+
9+
Write a function that returns the maximized combined value of the items that you should pick as well as an array of
10+
the indices of each item picked.
11+
12+
Sample Input:= [[1, 2], [4, 3], [5, 6], [6, 7]]
13+
Output:= [10, [1, 3]] // items [4, 3] and [6, 7]
14+
15+
Explanation:
16+
17+
Sure! Let's break down the code step by step:
18+
19+
1. `KnapsackProblem` function: This function takes in two arguments - `items`, a 2D slice representing the
20+
list of items with their values and weights, and `capacity`, an integer representing the maximum weight
21+
capacity of the knapsack. It returns an interface slice containing the maximum value that can be achieved
22+
and the sequence of items included in the knapsack to achieve that maximum value.
23+
24+
2. Initializing the `values` array: The function creates a 2D slice called `values` to store the maximum
25+
achievable values for different knapsack configurations. The size of this array is `(len(items)+1) x (capacity+1)`,
26+
where `(len(items)+1)` represents the number of items, and `(capacity+1)` represents the weight capacity of the knapsack.
27+
The `values` array will be filled during the dynamic programming process.
28+
29+
3. Filling the `values` array: The function iterates through the `items` array and fills the `values`
30+
array using dynamic programming. For each item at index `i`, the function calculates the maximum achievable
31+
value for all possible capacities from `0` to `capacity`.
32+
33+
4. Inner loop: The inner loop iterates from `0` to `capacity` and calculates the maximum achievable value for
34+
the current item at index `i` and the current capacity `c`.
35+
36+
5. Updating the `values` array: There are two possibilities for each item:
37+
a. If the weight of the current item `items[i-1][1]` is greater than the current capacity `c`, we cannot
38+
include the item in the knapsack at this capacity. So, we use the value from the previous row `values[i-1][c]`
39+
for the current cell `values[i][c]`.
40+
b. If we can include the current item, we have two choices:
41+
i. Not include the current item, so the value remains the same as in the previous row `values[i-1][c]`.
42+
ii. Include the current item, which adds its value `items[i-1][0]` to the value of the knapsack at capacity `c - items[i-1][1]`.
43+
We choose the maximum of these two options and update the current cell `values[i][c]`.
44+
45+
6. Finding the maximum value: Once the `values` array is filled, the maximum achievable value for the knapsack is stored in the
46+
bottom-right cell `values[len(items)][capacity]`.
47+
48+
7. Calling `getKnapSackItems` function: The function calls the `getKnapSackItems` function to find the sequence of items included in
49+
the knapsack to achieve the maximum value.
50+
51+
8. `getKnapSackItems` function: This function takes in the `values` array and the `items` array as input and returns a slice containing
52+
the indices of the items included in the knapsack.
53+
54+
9. Traversing back to find the items: Starting from the bottom-right cell of the `values` array, the function traverses back to find the
55+
items included in the knapsack. It does this by comparing the value in the current cell `values[i][c]` with the value in the cell above
56+
`values[i-1][c]`. If the values are the same, it means the current item was not included, so it moves to the previous row. Otherwise,
57+
it means the current item was included, so it adds the index of the current item `(i-1)` to the `sequence` slice and updates the capacity `c` accordingly.
58+
59+
10. Reversing the `sequence`: The sequence of items is built in reverse order, so the function uses the `reverse` helper function to
60+
reverse the order of elements in the `sequence` slice.
61+
62+
11. Returning the result: The function returns the maximum value and the sequence of items included in the knapsack as an interface slice.
63+
64+
12. Helper functions: The `max` function is a simple helper function that returns the maximum of two integers, and the `reverse`
65+
function is used to reverse the order of elements in a slice.
66+
67+
Time and Space complexity:
68+
O(nc) time | O(nc) space - where n is the number of items and c is the capacity
69+
'''
70+
def knapsack_problem(items, capacity):
71+
# Create a 2D list to store the values of different knapsack configurations.
72+
values = [[0] * (capacity + 1) for _ in range(len(items) + 1)]
73+
74+
# Iterate through the items and fill the values list.
75+
for i in range(1, len(items) + 1):
76+
current_value = items[i - 1][0]
77+
current_weight = items[i - 1][1]
78+
79+
for c in range(capacity + 1):
80+
# If the current item's weight is more than the current capacity (c),
81+
# then we cannot include it, so we use the value from the previous row (i - 1).
82+
if current_weight > c:
83+
values[i][c] = values[i - 1][c]
84+
else:
85+
# If we can include the current item, we have two choices:
86+
# 1. Not include the current item, so the value remains the same as the previous row.
87+
# 2. Include the current item, which adds its value to the value of the knapsack at capacity (c - current_weight).
88+
# We choose the maximum of these two options.
89+
values[i][c] = max(values[i - 1][c], values[i - 1][c - current_weight] + current_value)
90+
91+
# The value at the bottom-right corner of the values list represents the maximum achievable value for the knapsack problem.
92+
value = values[len(items)][capacity]
93+
94+
# Call the get_knapsack_items function to find the items that were included in the knapsack to achieve the maximum value.
95+
sequence = get_knapsack_items(values, items)
96+
97+
# Return the maximum value and the sequence of items included in the knapsack.
98+
return [value] + sequence
99+
100+
# get_knapsack_items is a helper function to find the sequence of items included in the knapsack.
101+
def get_knapsack_items(values, items):
102+
sequence = []
103+
i = len(values) - 1
104+
c = len(values[0]) - 1
105+
106+
# Starting from the bottom-right corner of the values list,
107+
# we traverse back to find the items included in the knapsack.
108+
while i > 0:
109+
if values[i][c] == values[i - 1][c]:
110+
# If the value is the same as in the previous row, it means the current item was not included.
111+
# So, we move to the previous row without adding the item to the sequence.
112+
i -= 1
113+
else:
114+
# If the value is greater than the value in the previous row, it means the current item was included.
115+
# So, we add the index of the current item (i-1) to the sequence and update the capacity (c) accordingly.
116+
sequence.append(i - 1)
117+
c -= items[i - 1][1]
118+
i -= 1
119+
# If the capacity becomes 0, it means we have included all the items needed to achieve the maximum value.
120+
if c == 0:
121+
break
122+
123+
# The sequence of items is built in reverse order, so we need to reverse it to get the correct order.
124+
sequence.reverse()
125+
return sequence

0 commit comments

Comments
 (0)