|
1 |
| -/* |
2 |
| -The Unbounded Knapsack problem allows you to take unlimited quantities of each item. The goal is to maximize the total value |
3 |
| -without exceeding the given knapsack capacity. Unlike the 0/1 knapsack, where each item can be taken only once, in this |
4 |
| -variation, you can pick any item as many times as needed, as long as the total weight stays within the knapsack's capacity. |
5 |
| -The problem is commonly solved using dynamic programming. |
| 1 | +/** |
| 2 | + * @file |
| 3 | + * @brief Unbounded Knapsack problem using Dynamic Programming |
| 4 | + * @details |
| 5 | + * The Unbounded Knapsack problem allows you to take unlimited quantities of each item. The goal is to maximize the total |
| 6 | + * value without exceeding the given knapsack capacity. Unlike the 0/1 knapsack, where each item can be taken only once, |
| 7 | + * in this variation, you can pick any item as many times as needed, as long as the total weight stays within the knapsack's capacity. |
| 8 | + * |
| 9 | + * @task Given a set of N items, each with a weight and a value, represented by the array `wt` and `val` respectively, and a knapsack |
| 10 | + * with a weight limit W, the task is to fill the knapsack in such a way that the maximum profit is obtained. Return the maximum profit. |
| 11 | + * |
| 12 | + * Note: Each item can be taken any number of times. |
| 13 | + * |
| 14 | + * @author [Sanskruti Yeole](https://github.com/yeolesanskruti) |
| 15 | + * @see dynamic_programming/Unbounded_knapsack.cpp |
| 16 | + */ |
6 | 17 |
|
7 |
| -TASK - Given a set of N items, each with a weight and a value, represented by the array wt and val respectively. Also, a knapsack with weight limit W. |
8 |
| -The task is to fill the knapsack in such a way that we can get the maximum profit. Return the maximum profit. |
9 |
| -Note: Each item can be taken any number of times. |
| 18 | +#include <iostream> |
| 19 | +#include <vector> |
| 20 | +#include <cassert> |
| 21 | +#include <cstdint> // for std::uint16_t |
10 | 22 |
|
11 |
| -Test Cases - |
12 |
| -Input: |
13 |
| -N = 4, W = 8, val[] = {6, 1, 7, 7}, wt[] = {1, 3, 4, 5} |
14 |
| -Output: |
15 |
| -48 |
16 |
| -*/ |
17 |
| - |
18 |
| -// Code |
19 |
| -#include <bits/stdc++.h> |
20 |
| -using namespace std; |
21 |
| - |
22 |
| -int KnapSackFilling(int i,int W, vector<int> val,vector<int> wt, vector<vector<int>> &dp){ |
23 |
| - if(i==0){ |
24 |
| - if(wt[0]<=W){ |
25 |
| - return (W/wt[0])*val[0]; |
26 |
| - }else{ |
| 23 | +/** |
| 24 | + * @brief Recursive function to calculate the maximum value that can be obtained |
| 25 | + * using an unbounded knapsack approach. |
| 26 | + * |
| 27 | + * @param i Current index in the value and weight vectors. |
| 28 | + * @param W Remaining capacity of the knapsack. |
| 29 | + * @param val Vector of values corresponding to the items. |
| 30 | + * @param wt Vector of weights corresponding to the items. |
| 31 | + * @param dp 2D vector for memoization to avoid redundant calculations. |
| 32 | + * @return The maximum value that can be obtained for the given index and capacity. |
| 33 | + */ |
| 34 | +int 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) { |
| 35 | + if (i == 0) { |
| 36 | + if (wt[0] <= W) { |
| 37 | + return (W / wt[0]) * val[0]; |
| 38 | + } else { |
27 | 39 | return 0;
|
28 | 40 | }
|
29 |
| - } |
30 |
| - if(dp[i][W]!=-1)return dp[i][W]; |
31 |
| - int nottake=KnapSackFilling(i-1,W,val,wt,dp); |
32 |
| - int take=0; |
33 |
| - if(W>=wt[i]){ |
34 |
| - take=val[i]+KnapSackFilling(i,W-wt[i],val,wt,dp); |
35 |
| - } |
36 |
| - return dp[i][W]=max(take,nottake); |
| 41 | + } |
| 42 | + if (dp[i][W] != -1) return dp[i][W]; |
| 43 | + |
| 44 | + int nottake = KnapSackFilling(i - 1, W, val, wt, dp); |
| 45 | + int take = 0; |
| 46 | + if (W >= wt[i]) { |
| 47 | + take = val[i] + KnapSackFilling(i, W - wt[i], val, wt, dp); |
| 48 | + } |
| 49 | + return dp[i][W] = std::max(take, nottake); |
37 | 50 | }
|
38 |
| -int unboundedKnapsack(int N, int W, vector<int> val, vector<int> wt) |
39 |
| -{ |
40 |
| - vector<vector<int>> dp(N,vector<int>(W+1,-1)); |
41 |
| - return KnapSackFilling(N-1,W,val,wt,dp); |
| 51 | + |
| 52 | +/** |
| 53 | + * @brief Wrapper function to initiate the unbounded knapsack calculation. |
| 54 | + * |
| 55 | + * @param N Number of items. |
| 56 | + * @param W Maximum weight capacity of the knapsack. |
| 57 | + * @param val Vector of values corresponding to the items. |
| 58 | + * @param wt Vector of weights corresponding to the items. |
| 59 | + * @return The maximum value that can be obtained for the given capacity. |
| 60 | + */ |
| 61 | +int unboundedKnapsack(std::uint16_t N, std::uint16_t W, const std::vector<std::uint16_t>& val, const std::vector<std::uint16_t>& wt) { |
| 62 | + std::vector<std::vector<int>> dp(N, std::vector<int>(W + 1, -1)); |
| 63 | + return KnapSackFilling(N - 1, W, val, wt, dp); |
42 | 64 | }
|
43 |
| -int main() { |
44 |
| - int N; |
45 |
| - N=4; |
46 |
| - vector<int> wt= {1, 3, 4, 5}; |
47 |
| - vector<int> val= {6, 1, 7, 7}; |
48 |
| - int W = 8; |
49 |
| - |
50 |
| - cout << "The Maximum value of items is " << unboundedKnapsack(N, W, val, wt) << endl; |
51 | 65 |
|
52 |
| - return 0; |
| 66 | +/** |
| 67 | + * @brief Function to run test cases for the unbounded knapsack implementation. |
| 68 | + */ |
| 69 | +void test_cases() { |
| 70 | + std::uint16_t N = 4; // Number of items |
| 71 | + std::vector<std::uint16_t> wt = {1, 3, 4, 5}; // Weights of the items |
| 72 | + std::vector<std::uint16_t> val = {6, 1, 7, 7}; // Values of the items |
| 73 | + std::uint16_t W = 8; // Maximum capacity of the knapsack |
| 74 | + |
| 75 | + // Test the function and assert the expected output |
| 76 | + assert(unboundedKnapsack(N, W, val, wt) == 48); |
| 77 | + std::cout << "All test cases passed!" << std::endl; |
53 | 78 | }
|
54 | 79 |
|
| 80 | +int main() { |
| 81 | + test_cases(); |
| 82 | + return 0; |
| 83 | +} |
0 commit comments