|
| 1 | +<div align="center"><h1>0/1 Knapsack</h1> |
| 2 | +<img src="./Images/knapsack_cover_pic.jpg"> |
| 3 | +</div></br> |
| 4 | + |
| 5 | +Language used : **Python3**</br> |
| 6 | +Source code : [python file](https://github.com/NeerajHazarika/PyAlgo-Tree/blob/main/Dynamic%20Programming/0%201%20Knapsack/01_knapsack.py) |
| 7 | + |
| 8 | +## 🎯 Aim |
| 9 | +To maximize profit/value in 0/1 Knapsack Problem |
| 10 | + |
| 11 | +## 🌟 Purpose |
| 12 | +To show the implementation of Top Down Dynamic Programming approach to solve 0/1 Knapsack Problem. |
| 13 | + |
| 14 | +## 📄 Description |
| 15 | +The knapsack problem is a problem in combinatorial optimization: Given a set of items, each with a weight and a value, take items to include in a knapsack such that the total weight is less than or equal to a given limit and the total value is as large as possible. Print the total value. |
| 16 | + |
| 17 | +Example: |
| 18 | +``` |
| 19 | +Input : |
| 20 | +val = [60, 100, 120 ] |
| 21 | +wt = [10, 20, 30 ] |
| 22 | +W = 50 |
| 23 | +
|
| 24 | +Output : |
| 25 | +220 |
| 26 | +``` |
| 27 | + |
| 28 | +## 🧮 Explanation |
| 29 | +A basic brute-force solution could be to try all combinations of the given items, allowing us to choose the one with maximum profit and a weight that doesn’t exceed ‘W.’ Take the example of 3 items, as shown in the diagram below. To try all the combinations, our algorithm will look like: |
| 30 | + |
| 31 | +<div align="center"> |
| 32 | +<img src="./Images/tree_dig.jpg"> |
| 33 | +</div></br> |
| 34 | + |
| 35 | +We can optimize this algorithm further with a 2D matrix. We can overcome the problem of calculating redundant cases and thus increased complexity. We can solve this problem by simply creating a 2-D array that can store a particular state (n, w) if we get it the first time. Now if we come across the same state (n, w) again instead of calculating it in exponential complexity we can directly return its result stored in the table in constant time. This method gives an edge over the recursive approach in this aspect. |
| 36 | + |
| 37 | +``` |
| 38 | +Let weight elements = {1, 2, 3} |
| 39 | +Let weight values = {10, 15, 40} |
| 40 | +Capacity=6 |
| 41 | +
|
| 42 | +We intialize a 2D MATRIX called DP with 0 to 3(no of items) rows and 0 to 6(max capacities possible) |
| 43 | +Each cell of this DP will represent max profit by selecting certain combination of items(through recursion) |
| 44 | +which is below or equal to max capacity of it's column, We initialize all cell values as -1. |
| 45 | +
|
| 46 | +Since we know our 2d dp matrix will be as shown below irrespective of the values of weights as |
| 47 | +not taking any element or max capacity=0 will give max profit = 0 so 0th row and 0th column are |
| 48 | +0, consider -1 to be null values: |
| 49 | + 0 1 2 3 4 5 6 (max capacities) |
| 50 | + - - - - - - - |
| 51 | +0 | 0 0 0 0 0 0 0 |
| 52 | +
|
| 53 | +1 | 0 |
| 54 | +
|
| 55 | +2 | 0 |
| 56 | +
|
| 57 | +3 | 0 |
| 58 | +(item no.) |
| 59 | +
|
| 60 | +Filling 1st row: |
| 61 | +For filling 'weight(i) = 1' we come across 'j = 1 to 6' in which we take maximum of : |
| 62 | +max(0, 0 + DP[1-1][j-1]) = 25, from j = 1 to 6, where 0=DP[i-1][j] in 1 not taken. |
| 63 | + | | |
| 64 | + '1' '1 taken' |
| 65 | + not taken |
| 66 | +
|
| 67 | + 0 1 2 3 4 5 6 |
| 68 | + - - - - - - - |
| 69 | +0 | 0 0 0 0 0 0 0 |
| 70 | +
|
| 71 | +1 | 0 10 10 10 10 10 10 |
| 72 | +
|
| 73 | +2 | 0 |
| 74 | +
|
| 75 | +3 | 0 |
| 76 | + |
| 77 | +Filling 2nd row: |
| 78 | +For filling 'weight(i) = 2' at 'j = 1' we take maximum of : |
| 79 | +max(10, 15 + DP[2-1][1-2]) = 10, where 10 = DP[i-1][j] and since for "15 + DP[2-1][1-2]" we will reach max weight limit |
| 80 | + | | so it cannot be taken, that why DP[2-1][1-2] is undefined and also not accessed |
| 81 | + '2' '2 taken' |
| 82 | + not taken |
| 83 | + |
| 84 | +For filling 'weight(i) = 2' at 'j = 2' we take maximum of : |
| 85 | +max(10, 15 + DP[2-1][2-2]) = 15, where 10 = DP[i-1][j] |
| 86 | + | | |
| 87 | + '2' '2 taken' |
| 88 | + not taken |
| 89 | + |
| 90 | +For filling 'weight(i) = 2' at 'j = 3 to 6' we take maximum of : |
| 91 | +max(10, 15 + DP[2-1][j-2]) = 25, where 10 = DP[i-1][j], and since all DP[1][1] to DP[1][6] has value 10, so 15+10=25 |
| 92 | + | | |
| 93 | + '2' '2 taken' |
| 94 | + not taken |
| 95 | +
|
| 96 | + 0 1 2 3 4 5 6 |
| 97 | + - - - - - - - |
| 98 | +0 | 0 0 0 0 0 0 0 |
| 99 | +
|
| 100 | +1 | 0 10 10 10 10 10 10 |
| 101 | +
|
| 102 | +2 | 0 10 15 25 25 25 25 |
| 103 | +
|
| 104 | +3 | 0 |
| 105 | + |
| 106 | +Filling 3rd row: |
| 107 | +For filling 'weight(i) = 3' at 'j = 1' we take maximum of : |
| 108 | +max(10, 40 + DP[3-1][1-3]) = 15, where 10 = DP[i-1][j], and since DP[3-1][1-3] isnt valid we take 10 as max |
| 109 | + | | |
| 110 | + '3' '3 taken' |
| 111 | + not taken |
| 112 | +
|
| 113 | +For filling 'weight(i) = 3' at 'j = 2' we take maximum of : |
| 114 | +max(15, 40 + DP[3-1][2-3]) = 15, where 10 = DP[i-1][j], and since DP[3-1][2-3] isnt valid we take 15 as max |
| 115 | + | | |
| 116 | + '3' '3 taken' |
| 117 | + not taken |
| 118 | +
|
| 119 | +For filling 'weight(i) = 3' at 'j = 3' we take maximum of : |
| 120 | +max(25, 40 + DP[3-1][3-3]) = 15, where 10 = DP[i-1][j], and since DP[3-1][3-3] is valid we take 40+0 as max |
| 121 | + | | |
| 122 | + '3' '3 taken' |
| 123 | + not taken |
| 124 | + |
| 125 | +similarly, when we reach 'weight(i) = 3' at 'j = 6' we take maximum of : |
| 126 | +max(25, 40 + DP[3-1][3-3]) = 15, where 10 = DP[i-1][j], and since DP[6-1][6-3] is valid we take 40+25 as max |
| 127 | + | | |
| 128 | + '3' '3 taken' |
| 129 | + not taken |
| 130 | +We have reached our solution for max profit (with max weight capacity = 6) at DP[3][6] (the last cell of our 2d matrix) |
| 131 | +
|
| 132 | + 0 1 2 3 4 5 6 |
| 133 | + - - - - - - - |
| 134 | +0 | 0 0 0 0 0 0 0 |
| 135 | +
|
| 136 | +1 | 0 10 10 10 10 10 10 |
| 137 | +
|
| 138 | +2 | 0 10 15 25 25 25 25 |
| 139 | +
|
| 140 | +3 | 0 10 15 40 50 55 65 |
| 141 | +``` |
| 142 | +## 💻 Input and Output |
| 143 | +- **Test Case 1 :** |
| 144 | + |
| 145 | + |
| 146 | + |
| 147 | +- **Test Case 2 :** |
| 148 | + |
| 149 | + |
| 150 | + |
| 151 | +## ⏰ Time and Space complexity |
| 152 | +- **Time Complexity:** `O(N*W)`. |
| 153 | +- **Space Complexity:** `O(N*W)`. |
| 154 | + |
| 155 | +## Author |
| 156 | +Neeraj Pratap Hazarika [@NeerajHazarika](https://github.com/NeerajHazarika) |
| 157 | + |
| 158 | +[](https://www.python.org/) |
0 commit comments