diff --git a/Knapsack/0-1 Knapsack/Brute Force Method/0-1_knapsack_brute_force.py b/Knapsack/0-1 Knapsack/Brute Force Method/0-1_knapsack_brute_force.py new file mode 100644 index 00000000..72b197f8 --- /dev/null +++ b/Knapsack/0-1 Knapsack/Brute Force Method/0-1_knapsack_brute_force.py @@ -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 diff --git a/Knapsack/0-1 Knapsack/Brute Force Method/README.md b/Knapsack/0-1 Knapsack/Brute Force Method/README.md new file mode 100644 index 00000000..5c3c7a29 --- /dev/null +++ b/Knapsack/0-1 Knapsack/Brute Force Method/README.md @@ -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/) diff --git a/Knapsack/0-1 Knapsack/Dynamic Method/0-1_knapsack_dynamic.py b/Knapsack/0-1 Knapsack/Dynamic Method/0-1_knapsack_dynamic.py new file mode 100644 index 00000000..73c4bbf8 --- /dev/null +++ b/Knapsack/0-1 Knapsack/Dynamic Method/0-1_knapsack_dynamic.py @@ -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 diff --git a/Knapsack/0-1 Knapsack/Dynamic Method/README.md b/Knapsack/0-1 Knapsack/Dynamic Method/README.md new file mode 100644 index 00000000..9e691a15 --- /dev/null +++ b/Knapsack/0-1 Knapsack/Dynamic Method/README.md @@ -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/) diff --git a/Knapsack/0-1 Knapsack/Images/knapsack1.PNG b/Knapsack/0-1 Knapsack/Images/knapsack1.PNG new file mode 100644 index 00000000..f5df83a5 Binary files /dev/null and b/Knapsack/0-1 Knapsack/Images/knapsack1.PNG differ diff --git a/Knapsack/0-1 Knapsack/Images/knapsack2.PNG b/Knapsack/0-1 Knapsack/Images/knapsack2.PNG new file mode 100644 index 00000000..ba393a1d Binary files /dev/null and b/Knapsack/0-1 Knapsack/Images/knapsack2.PNG differ diff --git a/Knapsack/0-1 Knapsack/Images/knapsack3.jpg b/Knapsack/0-1 Knapsack/Images/knapsack3.jpg new file mode 100644 index 00000000..67213921 Binary files /dev/null and b/Knapsack/0-1 Knapsack/Images/knapsack3.jpg differ diff --git a/Knapsack/0-1 Knapsack/README.md b/Knapsack/0-1 Knapsack/README.md new file mode 100644 index 00000000..41cb2b23 --- /dev/null +++ b/Knapsack/0-1 Knapsack/README.md @@ -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/) +