1- """A naive recursive implementation of 0-1 Knapsack Problem
1+ """A recursive implementation of 0-N Knapsack Problem
22https://en.wikipedia.org/wiki/Knapsack_problem
33"""
44
55from __future__ import annotations
66
7+ from functools import lru_cache
78
8- def knapsack (capacity : int , weights : list [int ], values : list [int ], counter : int ) -> int :
9+
10+ def knapsack (
11+ capacity : int ,
12+ weights : list [int ],
13+ values : list [int ],
14+ counter : int ,
15+ allow_repetition = False ,
16+ ) -> int :
917 """
1018 Returns the maximum value that can be put in a knapsack of a capacity cap,
11- whereby each weight w has a specific value val.
19+ whereby each weight w has a specific value val
20+ with option to allow repetitive selection of items
1221
1322 >>> cap = 50
1423 >>> val = [60, 100, 120]
@@ -17,28 +26,40 @@ def knapsack(capacity: int, weights: list[int], values: list[int], counter: int)
1726 >>> knapsack(cap, w, val, c)
1827 220
1928
20- The result is 220 cause the values of 100 and 120 got the weight of 50
29+ Given the repetition is NOT allowed,
30+ the result is 220 cause the values of 100 and 120 got the weight of 50
2131 which is the limit of the capacity.
32+ >>> knapsack(cap, w, val, c, True)
33+ 300
34+
35+ Given the repetition is allowed,
36+ the result is 300 cause the values of 60*5 (pick 5 times)
37+ got the weight of 10*5 which is the limit of the capacity.
2238 """
2339
24- # Base Case
25- if counter == 0 or capacity == 0 :
26- return 0
27-
28- # If weight of the nth item is more than Knapsack of capacity,
29- # then this item cannot be included in the optimal solution,
30- # else return the maximum of two cases:
31- # (1) nth item included
32- # (2) not included
33- if weights [counter - 1 ] > capacity :
34- return knapsack (capacity , weights , values , counter - 1 )
35- else :
36- left_capacity = capacity - weights [counter - 1 ]
37- new_value_included = values [counter - 1 ] + knapsack (
38- left_capacity , weights , values , counter - 1
39- )
40- without_new_value = knapsack (capacity , weights , values , counter - 1 )
41- return max (new_value_included , without_new_value )
40+ @lru_cache
41+ def knapsack_recur (capacity : int , counter : int ) -> int :
42+ # Base Case
43+ if counter == 0 or capacity == 0 :
44+ return 0
45+
46+ # If weight of the nth item is more than Knapsack of capacity,
47+ # then this item cannot be included in the optimal solution,
48+ # else return the maximum of two cases:
49+ # (1) nth item included only once (0-1), if allow_repetition is False
50+ # nth item included one or more times (0-N), if allow_repetition is True
51+ # (2) not included
52+ if weights [counter - 1 ] > capacity :
53+ return knapsack_recur (capacity , counter - 1 )
54+ else :
55+ left_capacity = capacity - weights [counter - 1 ]
56+ new_value_included = values [counter - 1 ] + knapsack_recur (
57+ left_capacity , counter - 1 if not allow_repetition else counter
58+ )
59+ without_new_value = knapsack_recur (capacity , counter - 1 )
60+ return max (new_value_included , without_new_value )
61+
62+ return knapsack_recur (capacity , counter )
4263
4364
4465if __name__ == "__main__" :
0 commit comments