View all POTD Solutions
Welcome to the daily solutions of our PROBLEM OF THE DAY (POTD). We will discuss the entire problem step-by-step and work towards developing an optimized solution. This will not only help you brush up on your concepts of Dynamic Programming but will also help you build up problem-solving skills.
 POTD 25 Oct’ 23
We recommend you to try this problem on our GeeksforGeeks Practice portal first, and maintain your streak to earn Geeksbits and other exciting prizes, before moving towards the solution.
POTD 25 October: Knapsack with Duplicate Items
Given a set of N items, each with a weight and a value, represented by the array w and val respectively. Also, a knapsack with weight limit W. The task is to fill the knapsack in such a way that we can get the maximum profit. Return the maximum profit. Note: Each item can be taken any number of times.
Example:
Input: W = 100 val[] = {1, 30} wt[] = {1, 50} Output: 100 There are many ways to fill knapsack. 1) 2 instances of 50 unit weight item. 2) 100 instances of 1 unit weight item. 3) 1 instance of 50 unit weight item and 50 instances of 1 unit weight items. We get maximum value with option 2.
Input: W = 8 val[] = {10, 40, 50, 70} wt[] = {1, 3, 4, 5} Output: 110 We get maximum value with one unit of weight 5 and one unit of weight 3.
Explores two choices at each step: including the current item if it doesn’t exceed the weight limit, or excluding it. The function uses a memoization table (‘dp’) to store and retrieve previously computed results to avoid redundant calculations. By recursively considering these choices and maximizing the total value, we find the optimal solution for the knapsack problem.
Below is the implantation of the above approach:
C++
class Solution {
public :
int rec( int i, int sum, int N, int W, int val[],
int wt[], vector<vector< int > >& dp)
{
if (i == N)
return 0;
if (dp[i][sum] != -1)
return dp[i][sum];
int w = wt[i];
int v = val[i];
int x = 0;
int y = 0;
if (w + sum <= W) {
x = v
+ rec(i, sum + w, N, W, val, wt,
dp);
}
y = rec(i + 1, sum, N, W, val, wt,
dp);
return dp[i][sum] = max(x, y);
}
int knapSack( int N, int W, int val[], int wt[])
{
vector<vector< int > > dp(N, vector< int >(W + 1, -1));
return rec(0, 0, N, W, val, wt, dp);
}
};
|
Java
class Solution {
static int rec( int i, int sum, int N, int W, int [] val,
int [] wt, int [][] dp)
{
if (i == N)
return 0 ;
if (dp[i][sum] != - 1 )
return dp[i][sum];
int w = wt[i];
int v = val[i];
int x = 0 ;
int y = 0 ;
if (w + sum <= W) {
x = v + rec(i, sum + w, N, W, val, wt, dp);
}
y = rec(i + 1 , sum, N, W, val, wt, dp);
return dp[i][sum] = Math.max(x, y);
}
static int knapSack( int N, int W, int val[], int wt[])
{
int [][] dp = new int [N][W + 1 ];
for ( int i = 0 ; i < N; i++) {
Arrays.fill(dp[i], - 1 );
}
return rec( 0 , 0 , N, W, val, wt, dp);
}
}
|
Python3
class Solution:
def rec( self , i, sum , N, W, val, wt, dp):
if i = = N:
return 0
if dp[i][ sum ] ! = - 1 :
return dp[i][ sum ]
w = wt[i]
v = val[i]
x = 0
y = 0
if w + sum < = W:
x = v + self .rec(i, sum + w, N, W, val, wt, dp)
y = self .rec(i + 1 , sum , N, W, val, wt, dp)
dp[i][ sum ] = max (x, y)
return dp[i][ sum ]
def knapSack( self , N, W, val, wt):
dp = [[ - 1 ] * (W + 1 ) for _ in range (N)]
return self .rec( 0 , 0 , N, W, val, wt, dp)
|
Time Complexity: O(N*W) Auxiliary Space: O(N*W)
Its an unbounded knapsack problem as we can use 1 or more instances of any resource. A simple 1D array, say dp[W+1] can be used such that dp[i] stores the maximum value which can achieved using all items with i capacity of knapsack. Note that we use 1D array here which is different from classical knapsack where we used 2D array. Here number of items never changes. We always have all items available. We can compute dp[] using below formula:
dp[i] = 0 dp[i] = max(dp[i], dp[i-wt[j]] + val[j], where j varies from 0 to n-1 such that: wt[j] <= i
result = dp[W]
Below is the implementation of above approach.
C++
class Solution {
public :
int knapSack( int N, int W, int val[], int wt[])
{
int dp[W + 1];
memset (dp, 0, sizeof dp);
for ( int i = 0; i <= W; i++) {
for ( int j = 0; j < N; j++) {
if (wt[j] <= i) {
dp[i] = max(dp[i],
dp[i - wt[j]] + val[j]);
}
}
}
return dp[W];
}
};
|
Java
class Solution {
static int knapSack( int N, int W, int val[], int wt[])
{
int [] dp = new int [W + 1 ];
for ( int i = 0 ; i <= W; i++) {
for ( int j = 0 ; j < N; j++) {
if (wt[j] <= i) {
dp[i] = Math.max(dp[i], dp[i - wt[j]]
+ val[j]);
}
}
}
return dp[W];
}
}
|
Python3
class Solution:
def knapSack( self , N, W, val, wt):
dp = [ 0 ] * (W + 1 )
for i in range (W + 1 ):
for j in range (N):
if wt[j] < = i:
dp[i] = max (dp[i], dp[i - wt[j]] + val[j])
return dp[W]
|
Time Complexity: O(N*W) Auxiliary Space: O(N*W)
|