Algorithms_in_C++ 1.0.0
Set of algorithms implemented in C++.
Loading...
Searching...
No Matches
Unbounded_0_1_Knapsack.cpp File Reference

Implementation of the Unbounded 0/1 Knapsack Problem. More...

#include <iostream>
#include <vector>
#include <cassert>
#include <cstdint>
Include dependency graph for Unbounded_0_1_Knapsack.cpp:

Namespaces

namespace  dynamic_programming
 Dynamic Programming algorithms.
 
namespace  Knapsack
 Implementation of 0-1 Knapsack problem.
 

Functions

std::uint16_t dynamic_programming::unbounded_knapsack::KnapSackFilling (std::uint16_t i, std::uint16_t W, const std::vector< std::uint16_t > &val, const std::vector< std::uint16_t > &wt, std::vector< std::vector< int > > &dp)
 Recursive function to calculate the maximum value obtainable using an unbounded knapsack approach.
 
std::uint16_t dynamic_programming::unbounded_knapsack::unboundedKnapsack (std::uint16_t N, std::uint16_t W, const std::vector< std::uint16_t > &val, const std::vector< std::uint16_t > &wt)
 Wrapper function to initiate the unbounded knapsack calculation.
 
static void tests ()
 self test implementation
 
int main ()
 main function
 

Detailed Description

Implementation of the Unbounded 0/1 Knapsack Problem.

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
See also
dynamic_programming/0_1_knapsack.cpp

Function Documentation

◆ KnapSackFilling()

std::uint16_t dynamic_programming::unbounded_knapsack::KnapSackFilling ( std::uint16_t i,
std::uint16_t W,
const std::vector< std::uint16_t > & val,
const std::vector< std::uint16_t > & wt,
std::vector< std::vector< int > > & dp )

Recursive function to calculate the maximum value obtainable using an unbounded knapsack approach.

Parameters
iCurrent index in the value and weight vectors.
WRemaining capacity of the knapsack.
valVector of values corresponding to the items.
Note
"val" data type can be changed according to the size of the input.
Parameters
wtVector of weights corresponding to the items.
Note
"wt" data type can be changed according to the size of the input.
Parameters
dp2D vector for memoization to avoid redundant calculations.
Returns
The maximum value that can be obtained for the given index and capacity.
60 {
61 if (i == 0) {
62 if (wt[0] <= W) {
63 return (W / wt[0]) * val[0]; // Take as many of the first item as possible
64 } else {
65 return 0; // Can't take the first item
66 }
67 }
68 if (dp[i][W] != -1) return dp[i][W]; // Return result if available
69
70 int nottake = KnapSackFilling(i - 1, W, val, wt, dp); // Value without taking item i
71 int take = 0;
72 if (W >= wt[i]) {
73 take = val[i] + KnapSackFilling(i, W - wt[i], val, wt, dp); // Value taking item i
74 }
75 return dp[i][W] = std::max(take, nottake); // Store and return the maximum value
76}
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, std::vector< std::vector< int > > &dp)
Recursive function to calculate the maximum value obtainable using an unbounded knapsack approach.
Definition Unbounded_0_1_Knapsack.cpp:57
T max(T... args)
for std::vector
Definition partition_problem.cpp:39
Here is the call graph for this function:

◆ main()

int main ( void )

main function

Returns
0 on successful exit
147 {
148 tests(); // Run self test implementation
149 return 0;
150}
static void tests()
self test implementation
Definition Unbounded_0_1_Knapsack.cpp:103
Here is the call graph for this function:

◆ tests()

static void tests ( )
static

self test implementation

Returns
void
103 {
104 // Test Case 1
105 std::uint16_t N1 = 4; // Number of items
106 std::vector<std::uint16_t> wt1 = {1, 3, 4, 5}; // Weights of the items
107 std::vector<std::uint16_t> val1 = {6, 1, 7, 7}; // Values of the items
108 std::uint16_t W1 = 8; // Maximum capacity of the knapsack
109 // Test the function and assert the expected output
110 assert(unboundedKnapsack(N1, W1, val1, wt1) == 48);
111 std::cout << "Maximum Knapsack value " << unboundedKnapsack(N1, W1, val1, wt1) << std::endl;
112
113 // Test Case 2
114 std::uint16_t N2 = 3; // Number of items
115 std::vector<std::uint16_t> wt2 = {10, 20, 30}; // Weights of the items
116 std::vector<std::uint16_t> val2 = {60, 100, 120}; // Values of the items
117 std::uint16_t W2 = 5; // Maximum capacity of the knapsack
118 // Test the function and assert the expected output
119 assert(unboundedKnapsack(N2, W2, val2, wt2) == 0);
120 std::cout << "Maximum Knapsack value " << unboundedKnapsack(N2, W2, val2, wt2) << std::endl;
121
122 // Test Case 3
123 std::uint16_t N3 = 3; // Number of items
124 std::vector<std::uint16_t> wt3 = {2, 4, 6}; // Weights of the items
125 std::vector<std::uint16_t> val3 = {5, 11, 13};// Values of the items
126 std::uint16_t W3 = 27;// Maximum capacity of the knapsack
127 // Test the function and assert the expected output
128 assert(unboundedKnapsack(N3, W3, val3, wt3) == 27);
129 std::cout << "Maximum Knapsack value " << unboundedKnapsack(N3, W3, val3, wt3) << std::endl;
130
131 // Test Case 4
132 std::uint16_t N4 = 0; // Number of items
133 std::vector<std::uint16_t> wt4 = {}; // Weights of the items
134 std::vector<std::uint16_t> val4 = {}; // Values of the items
135 std::uint16_t W4 = 10; // Maximum capacity of the knapsack
136 assert(unboundedKnapsack(N4, W4, val4, wt4) == 0);
137 std::cout << "Maximum Knapsack value for empty arrays: " << unboundedKnapsack(N4, W4, val4, wt4) << std::endl;
138
139 std::cout << "All test cases passed!" << std::endl;
140
141}
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)
Wrapper function to initiate the unbounded knapsack calculation.
Definition Unbounded_0_1_Knapsack.cpp:87
T endl(T... args)
Here is the call graph for this function:

◆ unboundedKnapsack()

std::uint16_t dynamic_programming::unbounded_knapsack::unboundedKnapsack ( std::uint16_t N,
std::uint16_t W,
const std::vector< std::uint16_t > & val,
const std::vector< std::uint16_t > & wt )

Wrapper function to initiate the unbounded knapsack calculation.

Parameters
NNumber of items.
WMaximum weight capacity of the knapsack.
valVector of values corresponding to the items.
wtVector of weights corresponding to the items.
Returns
The maximum value that can be obtained for the given capacity.
89 {
90 if(N==0)return 0; // Expect 0 since no items
91 std::vector<std::vector<int>> dp(N, std::vector<int>(W + 1, -1)); // Initialize memoization table
92 return KnapSackFilling(N - 1, W, val, wt, dp); // Start the calculation
93}
Here is the call graph for this function: