# Task 1: ``` def knapsack(capacity, weights, values, index): if index == 0 or capacity == 0: return 0 if weights[index - 1] > capacity: return knapsack(capacity, weights, values, n - 1) skip_item = knapsack(capacity, weights, values, n - 1) take_item = values[n - 1] + knapsack(capacity, weights, values, n - 1) return max(skip_item, take_item) ``` # Task 3: - Fractional which has a worst case runtime of O(nlogn) compared to the backtracking 0/1 knapsack solution which is exponential or O(2^n) - The greedy strategy for the 0/1 knapsack problems would still select the items in order of best value-to-weight ratio, but instead of "cutting" once the availabe capacity was less than the weight of the next item, it would just skip that item. 1. This approach would not always reach the optimal result. 2. The speed of the algorithm would be greatly improved from and exponential runtime to a linear-logarithmic runtime. - The following example input would produce a suboptimal solution with the greedy approach to the 0/1 knapsack problem. This is because It would take the first item which has the greates value-to-weight ratio (3) leaving it with a remaining capacity of 4 and unable to choose any of the remaining, leaving us with a final value of 18. The optimal solution in this case is to take the latter two for a total value of 20 and 0 remaining capacity. ``` 10 3 A 18 6 B 14 5 C 6 5 ```