Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# A naive recursive implementation
# of 0-1 Knapsack Problem
# Brute Force Method

# Problem Statement : Returns the maximum value that
# can be put in a knapsack of
# capacity W

# Author : Abhishek Sharma, 2021

# -----------------------------------------------------------------

# Solution for the above problem statement using Python 3 language.
# Approach : Brute Force Method

# -----------------------------------------------------------------

# This is the main function which will provide us maximum value that
# can be put in the capacity of W

def knapSack(W, wt, val, n):

# Base Case
if n == 0 or W == 0:
return 0

# If weight of the nth item is
# more than Knapsack of capacity W,
# then this item cannot be included
# in the optimal solution

if (wt[n-1] > W):
return knapSack(W, wt, val, n-1)

# return the maximum of two cases:
# (1) nth item included
# (2) not included

else:
return max(
val[n-1] + knapSack(
W-wt[n-1], wt, val, n-1),
knapSack(W, wt, val, n-1))


# end of function knapSack


#Driver Code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print ("- 0-1 Knapsack Problem using Brute Force Method - ")
print ("-----------------------------------------------------")
print ()
print ("The values given : ")
print (val)
print ("-----------------------------------------------------")
print ("The corresponding weights are :")
print (wt)
print ("-----------------------------------------------------")
print ("The maximum capacity can be : ")
print (W)
print ()
print ("-----------------------------------------------------")
print ("Output :\nMaximum total value of the Knapsack : ")
print (knapSack(W, wt, val, n))

# -----------------------------------------------------------------
# Input given :
# The values given :
# [60, 100, 120]
# -----------------------------------------------------
# The corresponding weights are :
# [10, 20, 30]
# -----------------------------------------------------
# The maximum capacity can be :
# 50

# -----------------------------------------------------
# Output :
# Maximum total value of the Knapsack :
# 220

# -----------------------------------------------------------------

# Code contributed by, Abhishek Sharma, 2021
53 changes: 53 additions & 0 deletions Knapsack/0-1 Knapsack/Brute Force Method/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 0-1 Knapsack Problem using Brute Force Method
Language used : Python 3

## 📃 Approach
A simple solution is to consider all subsets of items and calculate the total weight and value of all subsets. Consider the only subsets whose total weight is smaller than W. From all such subsets, pick the maximum value subset.
Optimal Sub-structure: To consider all subsets of items, there can be two cases for every item.

- **Case 1:** The item is included in the optimal subset.
- **Case 2:** The item is not included in the optimal set.

Therefore, the maximum value that can be obtained from ‘n’ items is the max of the following two values.
- Maximum value obtained by n-1 items and W weight (excluding nth item).
- Value of nth item plus maximum value obtained by n-1 items and W minus the weight of the nth item (including nth item).

If the weight of ‘nth’ item is greater than ‘W’, then the nth item cannot be included and Case 1 is the only possibility.

## 🧮 Algorithm
It should be noted that the above function computes the same sub-problems again and again. See the following recursion tree, K(1, 1) is being evaluated twice. The time complexity of this naive recursive solution is exponential (2^n).

```
In the following recursion tree, K() refers
to knapSack(). The two parameters indicated in the
following recursion tree are n and W.
The recursion tree is for following sample inputs.
wt[] = {1, 1, 1}, W = 2, val[] = {10, 20, 30}
K(n, W)
K(3, 2)
/ \
/ \
K(2, 2) K(2, 1)
/ \ / \
/ \ / \
K(1, 2) K(1, 1) K(1, 1) K(1, 0)
/ \ / \ / \
/ \ / \ / \
K(0, 2) K(0, 1) K(0, 1) K(0, 0) K(0, 1) K(0, 0)
Recursion tree for Knapsack capacity 2
units and 3 items of 1 unit weight.
```

## 💻 Input and Output
![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Knapsack/0-1%20Knapsack/Images/knapsack2.PNG)


## ⏰ Complexity Analysis:
- **Time Complexity:** `O(2^n)`. [As there are redundant subproblems.]
- **Auxiliary Space :** `O(1)`. [As no extra data structure has been used for storing values.]

---------------------------------------------------------------
## 🖋️ Author
**Code contributed by, _Abhishek Sharma_, 2021 [@abhisheks008](github.com/abhisheks008)**

[![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)
79 changes: 79 additions & 0 deletions Knapsack/0-1 Knapsack/Dynamic Method/0-1_knapsack_dynamic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# A Dynamic Programming based Python
# Program for 0-1 Knapsack problem
# Returns the maximum value that can
# be put in a knapsack of capacity W

# Problem Statement : Returns the maximum value that
# can be put in a knapsack of
# capacity W

# Author : Abhishek Sharma, 2021

# -----------------------------------------------------------------

# Solution for the above problem statement using Python 3 language.
# Approach : Dynamic Method

# -----------------------------------------------------------------

# This is the main function which will provide us maximum value that
# can be put in the capacity of W

def knapSack(W, wt, val, n):
K = [[0 for x in range(W + 1)] for x in range(n + 1)]

# Build table K[][] in bottom up manner
for i in range(n + 1):
for w in range(W + 1):
if i == 0 or w == 0:
K[i][w] = 0
elif wt[i-1] <= w:
K[i][w] = max(val[i-1]
+ K[i-1][w-wt[i-1]],
K[i-1][w])
else:
K[i][w] = K[i-1][w]

return K[n][W]


# Driver code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print ("- 0-1 Knapsack Problem using Dynamic Method - ")
print ("-----------------------------------------------------")
print ()
print ("The values given : ")
print (val)
print ("-----------------------------------------------------")
print ("The corresponding weights are :")
print (wt)
print ("-----------------------------------------------------")
print ("The maximum capacity can be : ")
print (W)
print ()
print ("-----------------------------------------------------")
print ("Output :\nMaximum total value of the Knapsack : ")
print (knapSack(W, wt, val, n))

# -----------------------------------------------------------------
# Input given :
# The values given :
# [60, 100, 120]
# -----------------------------------------------------
# The corresponding weights are :
# [10, 20, 30]
# -----------------------------------------------------
# The maximum capacity can be :
# 50

# -----------------------------------------------------
# Output :
# Maximum total value of the Knapsack :
# 220

# -----------------------------------------------------------------

# Code contributed by, Abhishek Sharma, 2021
79 changes: 79 additions & 0 deletions Knapsack/0-1 Knapsack/Dynamic Method/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 0-1 Knapsack Problem using Dynamic Method
Language used : Python 3

## 📃 Approach
In the Dynamic programming we will work considering the same cases as mentioned in the recursive approach. In a `DP[][]` table let’s consider all the possible weights from ‘1’ to ‘W’ as the columns and weights that can be kept as the rows.

The state `DP[i][j]` will denote maximum value of ‘j-weight’ considering all values from ‘1 to ith’. So if we consider `‘wi’` (weight in ‘ith’ row) we can fill it in all columns which have ‘weight values > wi’. Now two possibilities can take place:

- Fill `‘wi’` in the given column.
- Do not fill ‘wi’ in the given column.

Now we have to take a maximum of these two possibilities, formally if we do not fill `‘ith’` weight in `‘jth’`column then `DP[i][j]` state will be same as `DP[i-1][j]` but if we fill the weight, `DP[i][j]` will be equal to the value of `‘wi’+` value of the column weighing `‘j-wi’` in the previous row. So we take the maximum of these two possibilities to fill the current state.

## 🧮 Algorithm
Let's visualize the algorithm here,

```
Let weight elements = {1, 2, 3}
Let weight values = {10, 15, 40}
Capacity=6

0 1 2 3 4 5 6

0 0 0 0 0 0 0 0

1 0 10 10 10 10 10 10

2 0 10 15 25 25 25 25

3 0

Explanation:
For filling 'weight = 2' we come
across 'j = 3' in which
we take maximum of
(10, 15 + DP[1][3-2]) = 25
| |
'2' '2 filled'
not filled

0 1 2 3 4 5 6

0 0 0 0 0 0 0 0

1 0 10 10 10 10 10 10

2 0 10 15 25 25 25 25

3 0 10 15 40 50 55 65

Explanation:
For filling 'weight=3',
we come across 'j=4' in which
we take maximum of (25, 40 + DP[2][4-3])
= 50

For filling 'weight=3'
we come across 'j=5' in which
we take maximum of (25, 40 + DP[2][5-3])
= 55

For filling 'weight=3'
we come across 'j=6' in which
we take maximum of (25, 40 + DP[2][6-3])
= 65
```

## 💻 Input and Output
![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Knapsack/0-1%20Knapsack/Images/knapsack1.PNG)

## ⏰ Complexity Analysis
- **Time Complexity:** `O(N*W)`. [where ‘N’ is the number of weight element and ‘W’ is capacity. As for every weight element we traverse through all weight capacities 1<=w<=W.]
- **Auxiliary Space :** `O(N*W)`. [The use of 2-D array of size `‘N*W’`.]

---------------------------------------------------------------
## 🖋️ Author
**Code contributed by, _Abhishek Sharma_, 2021 [@abhisheks008](github.com/abhisheks008)**

[![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)
Binary file added Knapsack/0-1 Knapsack/Images/knapsack1.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Knapsack/0-1 Knapsack/Images/knapsack2.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Knapsack/0-1 Knapsack/Images/knapsack3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions Knapsack/0-1 Knapsack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 0-1 Knapsack Problem
Language used : **Python 3**

![](https://github.com/abhisheks008/PyAlgo-Tree/blob/main/Knapsack/0-1%20Knapsack/Images/knapsack3.jpg)

## 🎯 Aim
The aim of this script is to find out the maximum value subset of val[] such that sum of the weights of this subset is smaller than or equal to W.

## 👉 Purpose
The main purpose of this script is to show the implementation of Brute Force method and Dynamic Programming method to solve the 0-1 Knapsack problem.

## 📄 Description
Given weights and values of `n` items, put these items in a knapsack of capacity `W` to get the maximum total value in the knapsack. In other words, given two integer arrays `val[0..n-1]` and `wt[0..n-1]` which represent values and weights associated with `n` items respectively. Also given an integer `W` which represents knapsack capacity, find out the maximum value subset of `val[]` such that sum of the weights of this subset is smaller than or equal to `W`. You cannot break an item, either pick the complete item or don’t pick it `(0-1 property)`.

## 📈 Workflow of the script
- `knapsack` - This is the main function which will provide us maximum value that can be put in the capacity of W.
- `main` - This is the driver code for this code/script.

## 🧮 Algorithms and Explanation
Here to solve the 0-1 Knapsack problem, I have used two different types of methods,
- **Brute Force Method** - The brute force approach is a guaranteed way to find the correct solution by listing all the possible candidate solutions for the problem. It is a generic method and not limited to any specific domain of problems. The brute force method is ideal for solving small and simpler problems.

🔴 **You can find out the approach of Brute Force Method to solve the 0-1 Knapsack problem, [here ✔️](https://github.com/abhisheks008/PyAlgo-Tree/tree/main/Knapsack/0-1%20Knapsack/Brute%20Force%20Method)**


- **Dynamic Method** - Dynamic programming is a technique that breaks the problems into sub-problems, and saves the result for future purposes so that we do not need to compute the result again. The subproblems are optimized to optimize the overall solution is known as optimal substructure property. The main use of dynamic programming is to solve optimization problems. Here, optimization problems mean that when we are trying to find out the minimum or the maximum solution of a problem. The dynamic programming guarantees to find the optimal solution of a problem if the solution exists. The definition of dynamic programming says that it is a technique for solving a complex problem by first breaking into a collection of simpler subproblems, solving each subproblem just once, and then storing their solutions to avoid repetitive computations.

🔴 **You can find out the approach of Dynamic Method to solve the 0-1 Knapsack problem, [here ✔️](https://github.com/abhisheks008/PyAlgo-Tree/tree/main/Knapsack/0-1%20Knapsack/Dynamic%20Method)**

## 💻 Input and Output
```
The values given :
[60, 100, 120]
-----------------------------------------------------
The corresponding weights are :
[10, 20, 30]
-----------------------------------------------------
The maximum capacity can be :
50

-----------------------------------------------------
Output :
Maximum total value of the Knapsack :
220
```

## 📊 Comparison of two different methods
We have implemented both the algorithms and methods and also have checked the time and space complexities of them. The **Brute force method** is having the time complexity of `O(2^n)` and the **Dynamic Method** is having the time complexity of `O(N*W)`. From this, it is clearly visible that using **Dynamic Method** provides less time complexity which means that the program can be run smoothly with less time spent.

Hence, **Dynamic Method ✔️** is having the upper hand in between these two types of methods of solving!

---------------------------------------------------------------
## 🖋️ Author
**Code contributed by, _Abhishek Sharma_, 2021 [@abhisheks008](github.com/abhisheks008)**

[![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)