# 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
```
