Skip to content

Commit 967b609

Browse files
authored
Merge branch 'prathimacode-hub:main' into main
2 parents 809d296 + 2816c07 commit 967b609

File tree

6 files changed

+212
-0
lines changed

6 files changed

+212
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# This is the memoization approach of 0 / 1 Knapsack in Python in simple
2+
# Method : Dynamic Programming
3+
# Author : Neeraj Pratap Hazarika
4+
5+
# Problem Statement : 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.
6+
7+
# ------------------------------------------------------------
8+
9+
# declare universal scope 2d matrix, dp
10+
dp=[[]]
11+
12+
def knapsack(wt, val, W, n):
13+
14+
# base conditions
15+
if n == 0 or W == 0:
16+
return 0
17+
if dp[n][W] != -1:
18+
return dp[n][W]
19+
20+
# choice diagram code
21+
if wt[n-1] <= W:
22+
dp[n][W] = max(val[n-1] + knapsack(wt, val, W-wt[n-1], n-1), knapsack(wt, val, W, n-1))
23+
return dp[n][W]
24+
elif wt[n-1] > W:
25+
dp[n][W] = knapsack(wt, val, W, n-1)
26+
return dp[n][W]
27+
28+
# Driver code
29+
if __name__ == '__main__':
30+
# Inputs
31+
W = int(input("Enter the maximum weight the knapsack can hold : "))
32+
n = int(input("Enter number of items to be choosen from : "))
33+
print("Enter the weights to be choosen from : ")
34+
wt = list(map(int,input().strip().split()))[:n]
35+
print("Enter the values corresponding to these weights : ")
36+
val = list(map(int,input().strip().split()))[:n]
37+
38+
# Initialize 2d matrix, dp
39+
dp = [[-1 for i in range(W + 1)] for j in range(n + 1)]
40+
41+
print("Maximum profit : ",knapsack(wt, val, W, n))
42+
43+
# ------------------------------------------------------------
44+
45+
# Inputs given :
46+
# Enter the maximum weight the knapsack can hold : 50
47+
# Enter number of items to be choosen from : 3
48+
# Enter the weights to be choosen from :
49+
# 10 20 30
50+
# Enter the values corresponding to these weights :
51+
# 60 100 120
52+
53+
# Output :
54+
# Maximum profit : 220
6.92 KB
Loading
6.82 KB
Loading
26 KB
Loading
23.1 KB
Loading
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
![io 1](./Images/io_1.png)
146+
147+
- **Test Case 2 :**
148+
149+
![io 2](./Images/io_2.png)
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+
[![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)

0 commit comments

Comments
 (0)