Given an integer W, arrays val[] and wt[], where val[i] and wt[i] are the values and weights of the ith item, the task is to calculate the maximum value that can be obtained using weights not exceeding W.
Note: Each weight can be included multiple times.
Examples:
Input: W = 4, val[] = {6, 18}, wt[] = {2, 3}
Output: 18
Explanation: The maximum value that can be obtained is 18, by selecting the 2nd item twice.Input: W = 50, val[] = {6, 18}, wt[] = {2, 3}
Output: 294
Naive Approach: Refer to the previous post to solve the problem using traditional Unbounded Knapsack algorithm.Â
Time Complexity: O(N * W)
Auxiliary Space: O(W)
Efficient Approach:Â The above approach can be optimized based on the following observations:
- Suppose the ith index gives us the maximum value per unit weight in the given data, which can be easily found in O(n).
- For any weight X, greater than or equal to wt[i], the maximum reachable value will be dp[X – wt[i]] + val[i].
- We can calculate the values of dp[] from 0 to wt[i] using the traditional algorithm and we can also calculate the number of instances of ith item we can fit in W weight.
- So the required answer will be val[i] * (W/wt[i]) + dp[W%wt[i]].
Â
Below is the implementation of  new algorithm.
C++
// C++ program to implement optimized Unbounded Knapsack // algorithm #include <bits/stdc++.h> using namespace std; Â
// Function to implement optimized // Unbounded Knapsack algorithm int unboundedKnapsackBetter( int W, vector< int > val, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â vector< int > wt) { Â
    // Stores most dense item     int maxDenseIndex = 0; Â
    // Find the item with highest unit value     // (if two items have same unit value then choose the     // lighter item)     for ( int i = 1; i < val.size(); i++) {         if (val[i] / wt[i]                 > val[maxDenseIndex] / wt[maxDenseIndex]             || (val[i] / wt[i]                     == val[maxDenseIndex]                            / wt[maxDenseIndex]                 && wt[i] < wt[maxDenseIndex])) {             maxDenseIndex = i;         }     } Â
    int dp[W + 1] = { 0 }; Â
    int counter = 0;     bool breaked = false ;     int i = 0;     for (i = 0; i <= W; i++) {         for ( int j = 0; j < wt.size(); j++) {             if (wt[j] <= i) {                 dp[i] = max(dp[i], dp[i - wt[j]] + val[j]);             }         }         if (i - wt[maxDenseIndex] >= 0             && dp[i] - dp[i - wt[maxDenseIndex]]                    == val[maxDenseIndex]) {             counter += 1;             if (counter >= wt[maxDenseIndex]) {                 breaked = true ;                 break ;             }         }         else {             counter = 0;         }     } Â
    if (!breaked) {         return dp[W];     }     else {         int start = i - wt[maxDenseIndex] + 1;         int times             = ( floor )((W - start) / wt[maxDenseIndex]);         int index = (W - start) % wt[maxDenseIndex] + start;         return (times * val[maxDenseIndex] + dp[index]);     } } Â
// Driver Code int main() { Â Â Â Â int W = 100; Â Â Â Â vector< int > val = { 10, 30, 20 }; Â Â Â Â vector< int > wt = { 5, 10, 15 }; Â Â Â Â cout << unboundedKnapsackBetter(W, val, wt); } Â
// This code is contributed by ratiagrawal. |
Java
import java.io.*; import java.lang.*; import java.util.*; Â
// class to implement optimized Unbounded Knapsack algorithm class Main { Â
    // function to implement optimized Unbounded Knapsack     // algorithm     public static int     unboundedKnapsackBetter( int W, int [] val, int [] wt)     { Â
        // find the item with highest unit value         int maxDenseIndex = 0 ;         for ( int i = 1 ; i < val.length; i++) {             if (val[i] / wt[i]                     > val[maxDenseIndex] / wt[maxDenseIndex]                 || (val[i] / wt[i]                         == val[maxDenseIndex]                                / wt[maxDenseIndex]                     && wt[i] < wt[maxDenseIndex])) {                 maxDenseIndex = i;             }         } Â
        int [] dp = new int [W + 1 ];         int counter = 0 ;         boolean breaked = false ;         int i = 0 ; Â
        // dynamic programming step         for (i = 0 ; i <= W; i++) {             for ( int j = 0 ; j < wt.length; j++) {                 if (wt[j] <= i) {                     dp[i] = Math.max(dp[i], dp[i - wt[j]]                                                 + val[j]);                 }             }             if (i - wt[maxDenseIndex] >= 0                 && dp[i] - dp[i - wt[maxDenseIndex]]                        == val[maxDenseIndex]) {                 counter += 1 ;                 if (counter >= wt[maxDenseIndex]) {                     breaked = true ;                     break ;                 }             }             else {                 counter = 0 ;             }         } Â
        if (!breaked) {             return dp[W];         }         else {             int start = i - wt[maxDenseIndex] + 1 ;             int times                 = ( int )((W - start) / wt[maxDenseIndex]);             int index                 = (W - start) % wt[maxDenseIndex] + start;             return (times * val[maxDenseIndex] + dp[index]);         }     } Â
    // Driver Code     public static void main(String[] args)     {         int W = 100 ;         int [] val = { 10 , 30 , 20 };         int [] wt = { 5 , 10 , 15 }; Â
        System.out.println(             unboundedKnapsackBetter(W, val, wt));     } } |
Python3
# Python Program to implement the above approach Â
from fractions import Fraction Â
# Function to implement optimized # Unbounded Knapsack algorithm Â
Â
def unboundedKnapsackBetter(W, val, wt): Â
    # Stores most dense item     maxDenseIndex = 0 Â
    # Find the item with highest unit value     # (if two items have same unit value then choose the lighter item)     for i in range ( 1 , len (val)): Â
        if Fraction(val[i], wt[i]) \             > Fraction(val[maxDenseIndex], wt[maxDenseIndex]) \             or (Fraction(val[i], wt[i]) = = Fraction(val[maxDenseIndex], wt[maxDenseIndex])                 and wt[i] < wt[maxDenseIndex]): Â
            maxDenseIndex = i Â
    dp = [ 0 for i in range (W + 1 )] Â
    counter = 0     breaked = False     for i in range (W + 1 ):         for j in range ( len (wt)): Â
            if (wt[j] < = i):                 dp[i] = max (dp[i], dp[i - wt[j]] + val[j]) Â
        if i - wt[maxDenseIndex] > = 0 \                 and dp[i] - dp[i - wt[maxDenseIndex]] = = val[maxDenseIndex]: Â
            counter + = 1 Â
            if counter > = wt[maxDenseIndex]: Â
                breaked = True                 # print(i)                 break         else :             counter = 0 Â
    if not breaked:         return dp[W]     else :         start = i - wt[maxDenseIndex] + 1         times = (W - start) / / wt[maxDenseIndex]         index = (W - start) % wt[maxDenseIndex] + start         return (times * val[maxDenseIndex] + dp[index]) Â
Â
# Driver Code W = 100 val = [ 10 , 30 , 20 ] wt = [ 5 , 10 , 15 ] Â
print (unboundedKnapsackBetter(W, val, wt)) |
C#
// C# program to implement optimized Unbounded Knapsack // algorithm using System; public class GFG { Â
    // function to implement optimized Unbounded Knapsack     // algorithm     static int unboundedKnapsackBetter( int W, int [] val,                                        int [] wt)     {         // find the item with highest unit value         int maxDenseIndex = 0;         for ( int j = 1; j < val.Length; j++) {             if (val[j] * 1.0 / wt[j]                     > val[maxDenseIndex] * 1.0                           / wt[maxDenseIndex]                 || (val[j] * 1.0 / wt[j]                         == val[maxDenseIndex] * 1.0                                / wt[maxDenseIndex]                     && wt[j] < wt[maxDenseIndex])) {                 maxDenseIndex = j;             }         } Â
        int [] dp = new int [W + 1];         int counter = 0;         bool breaked = false ;         int x = 0; Â
        // dynamic programming step         for (; x <= W; x++) {             for ( int j = 0; j < wt.Length; j++) {                 if (wt[j] <= x) {                     dp[x] = Math.Max(dp[x], dp[x - wt[j]]                                                 + val[j]);                 }             } Â
            if (x - wt[maxDenseIndex] >= 0                 && dp[x] - dp[x - wt[maxDenseIndex]]                        == val[maxDenseIndex]) {                 counter++;                 if (counter >= wt[maxDenseIndex]) {                     breaked = true ;                     break ;                 }             }             else {                 counter = 0;             }         } Â
        if (!breaked) {             return dp[W];         }         else {             int start = x - wt[maxDenseIndex] + 1;             int times = (W - start) / wt[maxDenseIndex];             int index                 = (W - start) % wt[maxDenseIndex] + start;             return (times * val[maxDenseIndex] + dp[index]);         }     } Â
    static public void Main()     { Â
        // Code         int W = 100;         int [] val = { 10, 30, 20 };         int [] wt = { 5, 10, 15 }; Â
        Console.WriteLine(             unboundedKnapsackBetter(W, val, wt));     } } Â
// This code is contributed by karthik. |
Javascript
// JavaScript program to implement optimized Unbounded Knapsack algorithm Â
// Function to implement optimized // Unbounded Knapsack algorithm function unboundedKnapsackBetter(W, val, wt) { Â
    // Stores most dense item     let maxDenseIndex = 0 Â
    // Find the item with highest unit value     // (if two items have same unit value then choose the lighter item)     for (let i = 1; i < val.length; i++) {         if (val[i] / wt[i] > val[maxDenseIndex] / wt[maxDenseIndex]             || (val[i] / wt[i] === val[maxDenseIndex] / wt[maxDenseIndex]                 && wt[i] < wt[maxDenseIndex])) {             maxDenseIndex = i;         }     } Â
    let dp = new Array(W + 1).fill(0); Â
    let counter = 0;     let breaked = false ;     for ( var i = 0; i <= W; i++) {         for (let j = 0; j < wt.length; j++) {             if (wt[j] <= i) {                 dp[i] = Math.max(dp[i], dp[i - wt[j]] + val[j]);             }         }         if (i - wt[maxDenseIndex] >= 0 && dp[i] - dp[i - wt[maxDenseIndex]] === val[maxDenseIndex]) {             counter += 1;             if (counter >= wt[maxDenseIndex]) {                 breaked = true ;                 break ;             }         } else {             counter = 0;         }     } Â
    if (!breaked) {         return dp[W];     } else {         let start = i - wt[maxDenseIndex] + 1;         let times = Math.floor((W - start) / wt[maxDenseIndex]);         let index = (W - start) % wt[maxDenseIndex] + start;         return (times * val[maxDenseIndex] + dp[index]);     } } Â
// Driver Code let W = 100; let val = [10, 30, 20]; let wt = [5, 10, 15]; console.log(unboundedKnapsackBetter(W, val, wt)); Â
// This code is contributed by lokeshpotta20. |
300
Time Complexity: O( N + min(wt[i], W) * N)
Auxiliary Space: O(W)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!