Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Unbounded_knapsack.cpp #2786

Merged
merged 28 commits into from
Oct 28, 2024
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d052748
Create Unbounded_knapsack.cpp
yeolesanskruti Oct 7, 2024
8b9f0c5
Update Unbounded_knapsack.cpp
yeolesanskruti Oct 8, 2024
a68f0e5
Update dynamic_programming/Unbounded_knapsack.cpp
yeolesanskruti Oct 8, 2024
f641dd3
Update dynamic_programming/Unbounded_knapsack.cpp
yeolesanskruti Oct 8, 2024
ff9f842
Update dynamic_programming/Unbounded_knapsack.cpp
yeolesanskruti Oct 8, 2024
43bc2ce
Update dynamic_programming/Unbounded_knapsack.cpp
yeolesanskruti Oct 8, 2024
5cc7245
Delete dynamic_programming/Unbounded_knapsack.cpp
yeolesanskruti Oct 8, 2024
6a8ca41
Create Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 8, 2024
e786129
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 8, 2024
47e2d1d
Merge branch 'TheAlgorithms:master' into master
yeolesanskruti Oct 8, 2024
d9c63ed
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 8, 2024
541ea54
docs: add docs for main
realstealthninja Oct 9, 2024
4d4c49c
Update dynamic_programming/Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 9, 2024
17f398f
Update dynamic_programming/Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 9, 2024
d7d96d7
Merge branch 'master' into master
yeolesanskruti Oct 9, 2024
122b453
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 10, 2024
59ef9d1
Merge branch 'master' into master
yeolesanskruti Oct 10, 2024
ddf1857
Merge branch 'master' into master
yeolesanskruti Oct 11, 2024
e99d523
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 11, 2024
4f17fb8
Merge branch 'master' into master
yeolesanskruti Oct 13, 2024
0cf4734
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 13, 2024
6faf04d
Update dynamic_programming/Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 14, 2024
675bc2b
Merge branch 'master' into master
yeolesanskruti Oct 14, 2024
783b156
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 15, 2024
20195f1
Update Unbounded_0_1_Knapsack.cpp
yeolesanskruti Oct 15, 2024
1e3cbd5
Merge branch 'master' into master
yeolesanskruti Oct 19, 2024
86ef381
Merge branch 'master' into master
realstealthninja Oct 24, 2024
b01227f
Merge branch 'master' into master
realstealthninja Oct 27, 2024
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
151 changes: 151 additions & 0 deletions dynamic_programming/Unbounded_0_1_Knapsack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
* @file
* @brief Implementation of the Unbounded 0/1 Knapsack Problem
*
* @details
* The Unbounded 0/1 Knapsack problem allows taking unlimited quantities of each item.
* The goal is to maximize the total value without exceeding the given knapsack capacity.
* Unlike the 0/1 knapsack, where each item can be taken only once, in this variation,
* any item can be picked any number of times as long as the total weight stays within
* the knapsack's capacity.
*
* Given a set of N items, each with a weight and a value, represented by the arrays
* `wt` and `val` respectively, and a knapsack with a weight limit W, the task is to
* fill the knapsack to maximize the total value.
*
* @note weight and value of items is greater than zero
*
* ### Algorithm
* The approach uses dynamic programming to build a solution iteratively.
* A 2D array is used for memoization to store intermediate results, allowing
* the function to avoid redundant calculations.
*
* @author [Sanskruti Yeole](https://github.com/yeolesanskruti)
* @see dynamic_programming/0_1_knapsack.cpp
*/

#include <iostream> // Standard input-output stream
#include <vector> // Standard library for using dynamic arrays (vectors)
#include <cassert> // For using assert function to validate test cases
#include <cstdint> // For fixed-width integer types like std::uint16_t

/**
* @namespace dynamic_programming
* @brief Namespace for dynamic programming algorithms
*/
namespace dynamic_programming {

/**
* @namespace Knapsack
* @brief Implementation of unbounded 0-1 knapsack problem
*/
namespace unbounded_knapsack {

/**
* @brief Recursive function to calculate the maximum value obtainable using
* an unbounded knapsack approach.
*
* @param i Current index in the value and weight vectors.
* @param W Remaining capacity of the knapsack.
* @param val Vector of values corresponding to the items.
* @note "val" data type can be changed according to the size of the input.
* @param wt Vector of weights corresponding to the items.
* @note "wt" data type can be changed according to the size of the input.
* @param dp 2D vector for memoization to avoid redundant calculations.
* @return The maximum value that can be obtained for the given index and capacity.
*/
std::uint16_t KnapSackFilling(std::uint16_t i, std::uint16_t W,
const std::vector<std::uint16_t>& val,
const std::vector<std::uint16_t>& wt,
realstealthninja marked this conversation as resolved.
Show resolved Hide resolved
std::vector<std::vector<int>>& dp) {
if (i == 0) {
if (wt[0] <= W) {
return (W / wt[0]) * val[0]; // Take as many of the first item as possible
} else {
return 0; // Can't take the first item
}
}
if (dp[i][W] != -1) return dp[i][W]; // Return result if available

int nottake = KnapSackFilling(i - 1, W, val, wt, dp); // Value without taking item i
int take = 0;
if (W >= wt[i]) {
take = val[i] + KnapSackFilling(i, W - wt[i], val, wt, dp); // Value taking item i
}
return dp[i][W] = std::max(take, nottake); // Store and return the maximum value
}

/**
* @brief Wrapper function to initiate the unbounded knapsack calculation.
*
* @param N Number of items.
* @param W Maximum weight capacity of the knapsack.
* @param val Vector of values corresponding to the items.
* @param wt Vector of weights corresponding to the items.
* @return The maximum value that can be obtained for the given capacity.
*/
std::uint16_t unboundedKnapsack(std::uint16_t N, std::uint16_t W,
const std::vector<std::uint16_t>& val,
const std::vector<std::uint16_t>& wt) {
if(N==0)return 0; // Expect 0 since no items
std::vector<std::vector<int>> dp(N, std::vector<int>(W + 1, -1)); // Initialize memoization table
return KnapSackFilling(N - 1, W, val, wt, dp); // Start the calculation
}

} // unbounded_knapsack

} // dynamic_programming

/**
* @brief self test implementation
* @return void
*/
static void tests() {
// Test Case 1
std::uint16_t N1 = 4; // Number of items
std::vector<std::uint16_t> wt1 = {1, 3, 4, 5}; // Weights of the items
std::vector<std::uint16_t> val1 = {6, 1, 7, 7}; // Values of the items
std::uint16_t W1 = 8; // Maximum capacity of the knapsack
// Test the function and assert the expected output
assert(unboundedKnapsack(N1, W1, val1, wt1) == 48);
std::cout << "Maximum Knapsack value " << unboundedKnapsack(N1, W1, val1, wt1) << std::endl;

realstealthninja marked this conversation as resolved.
Show resolved Hide resolved
// Test Case 2
std::uint16_t N2 = 3; // Number of items
std::vector<std::uint16_t> wt2 = {10, 20, 30}; // Weights of the items
std::vector<std::uint16_t> val2 = {60, 100, 120}; // Values of the items
std::uint16_t W2 = 5; // Maximum capacity of the knapsack
// Test the function and assert the expected output
assert(unboundedKnapsack(N2, W2, val2, wt2) == 0);
realstealthninja marked this conversation as resolved.
Show resolved Hide resolved
std::cout << "Maximum Knapsack value " << unboundedKnapsack(N2, W2, val2, wt2) << std::endl;

// Test Case 3
std::uint16_t N3 = 3; // Number of items
std::vector<std::uint16_t> wt3 = {2, 4, 6}; // Weights of the items
std::vector<std::uint16_t> val3 = {5, 11, 13};// Values of the items
std::uint16_t W3 = 27;// Maximum capacity of the knapsack
// Test the function and assert the expected output
assert(unboundedKnapsack(N3, W3, val3, wt3) == 27);
std::cout << "Maximum Knapsack value " << unboundedKnapsack(N3, W3, val3, wt3) << std::endl;

// Test Case 4
std::uint16_t N4 = 0; // Number of items
std::vector<std::uint16_t> wt4 = {}; // Weights of the items
std::vector<std::uint16_t> val4 = {}; // Values of the items
std::uint16_t W4 = 10; // Maximum capacity of the knapsack
assert(unboundedKnapsack(N4, W4, val4, wt4) == 0);
std::cout << "Maximum Knapsack value for empty arrays: " << unboundedKnapsack(N4, W4, val4, wt4) << std::endl;

std::cout << "All test cases passed!" << std::endl;

}

realstealthninja marked this conversation as resolved.
Show resolved Hide resolved
/**
* @brief main function
* @return 0 on successful exit
*/
int main() {
tests(); // Run self test implementation
return 0;
}

Loading