/** * @file * @brief Implementation of [0-1 Knapsack Problem] * (https://en.wikipedia.org/wiki/Knapsack_problem) * * @details * 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) * * ### Algorithm * The idea 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. * * @author [Anmol](https://github.com/Anmol3299) * @author [Pardeep](https://github.com/Pardeep009) */ #include #include #include #include /** * @namespace dynamic_programming * @brief Dynamic Programming algorithms */ namespace dynamic_programming { /** * @namespace Knapsack * @brief Implementation of 0-1 Knapsack problem */ namespace knapsack { /** * @brief Picking up all those items whose combined weight is below * the given capacity and calculating the value of those picked items. Trying all * possible combinations will yield the maximum knapsack value. * @tparam n size of the weight and value array * @param capacity capacity of the carrying bag * @param weight array representing the weight of items * @param value array representing the value of items * @return maximum value obtainable with a given capacity. */ template int maxKnapsackValue(const int capacity, const std::array &weight, const std::array &value) { std::vector > maxValue(n + 1, std::vector(capacity + 1, 0)); // outer loop will select no of items allowed // inner loop will select the capacity of the knapsack bag int items = sizeof(weight) / sizeof(weight[0]); for (size_t i = 0; i < items + 1; ++i) { for (size_t j = 0; j < capacity + 1; ++j) { if (i == 0 || j == 0) { // if no of items is zero or capacity is zero, then maxValue // will be zero maxValue[i][j] = 0; } else if (weight[i - 1] <= j) { // if the ith item's weight(in the actual array it will be at i-1) // is less than or equal to the allowed weight i.e. j then we // can pick that item for our knapsack. maxValue will be the // obtained either by picking the current item or by not picking // current item // picking the current item int profit1 = value[i - 1] + maxValue[i - 1][j - weight[i - 1]]; // not picking the current item int profit2 = maxValue[i - 1][j]; maxValue[i][j] = std::max(profit1, profit2); } else { // as the weight of the current item is greater than the allowed weight, so // maxProfit will be profit obtained by excluding the current item. maxValue[i][j] = maxValue[i - 1][j]; } } } // returning maximum value return maxValue[items][capacity]; } } // namespace knapsack } // namespace dynamic_programming /** * @brief Function to test the above algorithm * @returns void */ static void test() { // Test 1 const int n1 = 3; // number of items std::array weight1 = {10, 20, 30}; // weight of each item std::array value1 = {60, 100, 120}; // value of each item const int capacity1 = 50; // capacity of carrying bag const int max_value1 = dynamic_programming::knapsack::maxKnapsackValue( capacity1, weight1, value1); const int expected_max_value1 = 220; assert(max_value1 == expected_max_value1); std::cout << "Maximum Knapsack value with " << n1 << " items is " << max_value1 << std::endl; // Test 2 const int n2 = 4; // number of items std::array weight2 = {24, 10, 10, 7}; // weight of each item std::array value2 = {24, 18, 18, 10}; // value of each item const int capacity2 = 25; // capacity of carrying bag const int max_value2 = dynamic_programming::knapsack::maxKnapsackValue( capacity2, weight2, value2); const int expected_max_value2 = 36; assert(max_value2 == expected_max_value2); std::cout << "Maximum Knapsack value with " << n2 << " items is " << max_value2 << std::endl; } /** * @brief Main function * @returns 0 on exit */ int main() { // Testing test(); return 0; }