Given an array ‘arr’ containing the weight of ‘N’ distinct items, and two knapsacks that can withstand ‘W1’ and ‘W2’ weights, the task is to find the sum of the largest subset of the array ‘arr’, that can be fit in the two knapsacks. It’s not allowed to break any items in two, i.e an item should be put in one of the bags as a whole.
Examples:
Input : arr[] = {8, 3, 2}
W1 = 10, W2 = 3
Output : 13
First and third objects go in the first knapsack. The second object goes in the second knapsack. Thus, the total weight becomes 13.
Input : arr[] = {8, 5, 3}
W1 = 10, W2 = 3
Output : 11
Solution:
A recursive solution is to try out all the possible ways of filling the two knapsacks and choose the one giving the maximum weight.
To optimize the above idea, we need to determine the states of DP, that we will build up our solution upon. After little observation, we can determine that this can be represented in three states (i, w1_r, w2_r). Here ‘i’ means the index of the element we are trying to store, w1_r means the remaining space of the first knapsack, and w2_r means the remaining space of the second knapsack. Thus, the problem can be solved using a 3-dimensional dynamic-programming with a recurrence relation
DP[i][w1_r][w2_r] = max( DP[i + 1][w1_r][w2_r],
arr[i] + DP[i + 1][w1_r - arr[i]][w2_r],
arr[i] + DP[i + 1][w1_r][w2_r - arr[i]])
The explanation for the above recurrence relation is as follows:
For each ‘i’, we can either:
- Don’t select the item ‘i’.
- Fill the item ‘i’ in first knapsack.
- Fill the item ‘i’ in second knapsack.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#define maxN 31
#define maxW 31
using namespace std;
int dp[maxN][maxW][maxW];
int maxWeight( int * arr, int n, int w1_r, int w2_r, int i)
{
if (i == n)
return 0;
if (dp[i][w1_r][w2_r] != -1)
return dp[i][w1_r][w2_r];
int fill_w1 = 0, fill_w2 = 0, fill_none = 0;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i], w2_r, i + 1);
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r - arr[i], i + 1);
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1);
dp[i][w1_r][w2_r] = max(fill_none, max(fill_w1, fill_w2));
return dp[i][w1_r][w2_r];
}
int main()
{
int arr[] = { 8, 2, 3 };
memset (dp, -1, sizeof (dp));
int n = sizeof (arr) / sizeof (arr[0]);
int w1 = 10, w2 = 3;
cout << maxWeight(arr, n, w1, w2, 0);
return 0;
}
|
Java
class GFG
{
static int maxN = 31 ;
static int maxW = 31 ;
static int dp [][][] = new int [maxN][maxW][maxW];
static int maxWeight( int arr [] , int n, int w1_r, int w2_r, int i)
{
if (i == n)
return 0 ;
if (dp[i][w1_r][w2_r] != - 1 )
return dp[i][w1_r][w2_r];
int fill_w1 = 0 , fill_w2 = 0 , fill_none = 0 ;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i], w2_r, i + 1 );
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r - arr[i], i + 1 );
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1 );
dp[i][w1_r][w2_r] = Math.max(fill_none, Math.max(fill_w1, fill_w2));
return dp[i][w1_r][w2_r];
}
public static void main (String[] args)
{
int arr[] = { 8 , 2 , 3 };
for ( int i = 0 ; i < maxN ; i++)
for ( int j = 0 ; j < maxW ; j++)
for ( int k = 0 ; k < maxW ; k++)
dp[i][j][k] = - 1 ;
int n = arr.length;
int w1 = 10 , w2 = 3 ;
System.out.println(maxWeight(arr, n, w1, w2, 0 ));
}
}
|
Python3
def maxWeight(arr, n, w1_r, w2_r, i):
if i = = n:
return 0
if dp[i][w1_r][w2_r] ! = - 1 :
return dp[i][w1_r][w2_r]
fill_w1, fill_w2, fill_none = 0 , 0 , 0
if w1_r > = arr[i]:
fill_w1 = arr[i] + maxWeight(arr, n, w1_r - arr[i],
w2_r, i + 1 )
if w2_r > = arr[i]:
fill_w2 = arr[i] + maxWeight(arr, n, w1_r,
w2_r - arr[i], i + 1 )
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1 )
dp[i][w1_r][w2_r] = max (fill_none, max (fill_w1,
fill_w2))
return dp[i][w1_r][w2_r]
if __name__ = = "__main__" :
arr = [ 8 , 2 , 3 ]
maxN, maxW = 31 , 31
dp = [[[ - 1 ] * maxW] * maxW] * maxN
n = len (arr)
w1, w2 = 10 , 3
print (maxWeight(arr, n, w1, w2, 0 ))
|
C#
using System;
class GFG
{
static int maxN = 31;
static int maxW = 31;
static int [ , , ] dp = new int [maxN, maxW, maxW];
static int maxWeight( int [] arr, int n, int w1_r,
int w2_r, int i)
{
if (i == n)
return 0;
if (dp[i ,w1_r, w2_r] != -1)
return dp[i, w1_r, w2_r];
int fill_w1 = 0, fill_w2 = 0, fill_none = 0;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i], w2_r, i + 1);
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r - arr[i], i + 1);
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1);
dp[i, w1_r, w2_r] = Math.Max(fill_none, Math.Max(fill_w1, fill_w2));
return dp[i, w1_r, w2_r];
}
public static void Main ()
{
int [] arr = { 8, 2, 3 };
for ( int i = 0; i < maxN ; i++)
for ( int j = 0; j < maxW ; j++)
for ( int k = 0; k < maxW ; k++)
dp[i, j, k] = -1;
int n = arr.Length;
int w1 = 10, w2 = 3;
Console.WriteLine(maxWeight(arr, n, w1, w2, 0));
}
}
|
Javascript
<script>
var maxN = 31
var maxW = 31
var dp = Array(maxN);
for ( var i=0;i<maxN;i++)
{
dp[i] = Array(maxW);
for ( var j =0; j<maxW; j++)
{
dp[i][j] = Array(maxW).fill(-1);
}
}
function maxWeight(arr, n, w1_r, w2_r, i)
{
if (i == n)
return 0;
if (dp[i][w1_r][w2_r] != -1)
return dp[i][w1_r][w2_r];
var fill_w1 = 0, fill_w2 = 0, fill_none = 0;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i],
w2_r, i + 1);
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r -
arr[i], i + 1);
fill_none = maxWeight(arr, n, w1_r,
w2_r, i + 1);
dp[i][w1_r][w2_r] = Math.max(fill_none,
Math.max(fill_w1, fill_w2));
return dp[i][w1_r][w2_r];
}
var arr = [8, 2, 3 ];
var n = arr.length;
var w1 = 10, w2 = 3;
document.write( maxWeight(arr, n, w1, w2, 0));
</script>
|
Time complexity: O(N*W1*W2)
Auxiliary Space: O(N*W1*W2))
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a 3-D DP to store the solution of the subproblems.
- Initialize the DP with base cases if (i == 0) then dp[i][w1_r][w2_r] = 0
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Return the final solution stored in return dp[n][w1][w2].
Implementation :
C++
#include <bits/stdc++.h>
#define maxN 31
#define maxW 31
using namespace std;
int dp[maxN][maxW][maxW];
int maxWeight( int * arr, int n, int w1, int w2)
{
for ( int i = 0; i <= n; i++)
{
for ( int w1_r = 0; w1_r <= w1; w1_r++)
{
for ( int w2_r = 0; w2_r <= w2; w2_r++)
{
if (i == 0)
dp[i][w1_r][w2_r] = 0;
else if (arr[i - 1] <= w1_r && arr[i - 1] <= w2_r)
dp[i][w1_r][w2_r] =
max(arr[i - 1] + dp[i - 1][w1_r - arr[i - 1]][w2_r],
max(arr[i - 1] + dp[i - 1][w1_r][w2_r - arr[i - 1]],
dp[i - 1][w1_r][w2_r]));
else if (arr[i - 1] <= w2_r)
dp[i][w1_r][w2_r] = max(arr[i - 1] + dp[i - 1][w1_r][w2_r - arr[i - 1]],
dp[i - 1][w1_r][w2_r]);
else if (arr[i - 1] <= w1_r)
dp[i][w1_r][w2_r] = max(arr[i - 1] + dp[i - 1][w1_r - arr[i - 1]][w2_r],
dp[i - 1][w1_r][w2_r]);
else
dp[i][w1_r][w2_r] = dp[i - 1][w1_r][w2_r];
}
}
}
return dp[n][w1][w2];
}
int main()
{
int arr[] = { 8, 2, 3 };
int n = sizeof (arr) / sizeof (arr[0]);
int w1 = 10, w2 = 3;
cout << maxWeight(arr, n, w1, w2);
return 0;
}
|
Java
import java.util.*;
public class Main
{
static int [][][] dp = new int [ 31 ][ 31 ][ 31 ];
public static int maxWeight( int [] arr, int n,
int w1, int w2)
{
for ( int i = 0 ; i <= n; i++) {
for ( int w1_r = 0 ; w1_r <= w1; w1_r++) {
for ( int w2_r = 0 ; w2_r <= w2; w2_r++) {
if (i == 0 ) {
dp[i][w1_r][w2_r] = 0 ;
}
else if (arr[i - 1 ] <= w1_r && arr[i - 1 ] <= w2_r) {
dp[i][w1_r][w2_r] = Math.max(
arr[i - 1 ] + dp[i - 1 ][w1_r - arr[i - 1 ]][w2_r],
Math.max(arr[i - 1 ] + dp[i - 1 ][w1_r][w2_r - arr[i - 1 ]], dp[i - 1 ][w1_r][w2_r]));
}
else if (arr[i - 1 ] <= w2_r) {
dp[i][w1_r][w2_r] = Math.max(arr[i - 1 ] + dp[i - 1 ][w1_r][w2_r - arr[i - 1 ]],
dp[i - 1 ][w1_r][w2_r]);
}
else if (arr[i - 1 ] <= w1_r) {
dp[i][w1_r][w2_r] = Math.max(arr[i - 1 ] + dp[i - 1 ][w1_r - arr[i - 1 ]][w2_r],
dp[i - 1 ][w1_r][w2_r]);
}
else {
dp[i][w1_r][w2_r] = dp[i - 1 ][w1_r][w2_r];
}
}
}
}
return dp[n][w1][w2];
}
public static void main(String[] args)
{
int [] arr = { 8 , 2 , 3 };
int n = arr.length;
int w1 = 10 , w2 = 3 ;
System.out.println(maxWeight(arr, n, w1, w2));
}
}
|
Python3
maxN = 31
maxW = 31
dp = [[[ 0 for _ in range (maxW)] for _ in range (maxW)] for _ in range (maxN)]
def maxWeight(arr, n, w1, w2):
for i in range (n + 1 ):
for w1_r in range (w1 + 1 ):
for w2_r in range (w2 + 1 ):
if i = = 0 :
dp[i][w1_r][w2_r] = 0
elif arr[i - 1 ] < = w1_r and arr[i - 1 ] < = w2_r:
dp[i][w1_r][w2_r] = max (
arr[i - 1 ] + dp[i - 1 ][w1_r - arr[i - 1 ]][w2_r],
max (
arr[i - 1 ] + dp[i - 1 ][w1_r][w2_r - arr[i - 1 ]],
dp[i - 1 ][w1_r][w2_r]
)
)
elif arr[i - 1 ] < = w2_r:
dp[i][w1_r][w2_r] = max (
arr[i - 1 ] + dp[i - 1 ][w1_r][w2_r - arr[i - 1 ]],
dp[i - 1 ][w1_r][w2_r]
)
elif arr[i - 1 ] < = w1_r:
dp[i][w1_r][w2_r] = max (
arr[i - 1 ] + dp[i - 1 ][w1_r - arr[i - 1 ]][w2_r],
dp[i - 1 ][w1_r][w2_r]
)
else :
dp[i][w1_r][w2_r] = dp[i - 1 ][w1_r][w2_r]
return dp[n][w1][w2]
if __name__ = = "__main__" :
arr = [ 8 , 2 , 3 ]
n = len (arr)
w1 = 10
w2 = 3
print (maxWeight(arr, n, w1, w2))
|
C#
using System;
public class KnapsackProblem
{
public static int MaxWeight( int [] arr, int n, int w1, int w2)
{
int [,,] dp = new int [n + 1, w1 + 1, w2 + 1];
for ( int i = 0; i <= n; i++)
{
for ( int w1_r = 0; w1_r <= w1; w1_r++)
{
for ( int w2_r = 0; w2_r <= w2; w2_r++)
{
if (i == 0)
dp[i, w1_r, w2_r] = 0;
else if (arr[i - 1] <= w1_r && arr[i - 1] <= w2_r)
dp[i, w1_r, w2_r] =
Math.Max(arr[i - 1] + dp[i - 1, w1_r - arr[i - 1], w2_r],
Math.Max(arr[i - 1] + dp[i - 1, w1_r, w2_r - arr[i - 1]],
dp[i - 1, w1_r, w2_r]));
else if (arr[i - 1] <= w2_r)
dp[i, w1_r, w2_r] = Math.Max(arr[i - 1] + dp[i - 1, w1_r, w2_r - arr[i - 1]],
dp[i - 1, w1_r, w2_r]);
else if (arr[i - 1] <= w1_r)
dp[i, w1_r, w2_r] = Math.Max(arr[i - 1] + dp[i - 1, w1_r - arr[i - 1], w2_r],
dp[i - 1, w1_r, w2_r]);
else
dp[i, w1_r, w2_r] = dp[i - 1, w1_r, w2_r];
}
}
}
return dp[n, w1, w2];
}
public static void Main()
{
int [] arr = { 8, 2, 3 };
int n = arr.Length;
int w1 = 10, w2 = 3;
Console.WriteLine(MaxWeight(arr, n, w1, w2));
}
}
|
Javascript
const maxN = 31;
const maxW = 31;
const dp = new Array(maxN).fill( null ).map(() =>
new Array(maxW).fill( null ).map(() =>
new Array(maxW).fill(0)));
function maxWeight(arr, n, w1, w2) {
for (let i = 0; i <= n; i++) {
for (let w1_r = 0; w1_r <= w1; w1_r++) {
for (let w2_r = 0; w2_r <= w2; w2_r++) {
if (i === 0)
{
dp[i][w1_r][w2_r] = 0;
}
else if (arr[i - 1] <= w1_r && arr[i - 1] <= w2_r)
{
dp[i][w1_r][w2_r] =
Math.max(
arr[i - 1] + dp[i - 1][w1_r - arr[i - 1]][w2_r],
Math.max(
arr[i - 1] + dp[i - 1][w1_r][w2_r - arr[i - 1]],
dp[i - 1][w1_r][w2_r]
)
);
}
else if (arr[i - 1] <= w2_r)
{
dp[i][w1_r][w2_r] = Math.max(
arr[i - 1] + dp[i - 1][w1_r][w2_r - arr[i - 1]],
dp[i - 1][w1_r][w2_r]
);
}
else if (arr[i - 1] <= w1_r)
{
dp[i][w1_r][w2_r] = Math.max(
arr[i - 1] + dp[i - 1][w1_r - arr[i - 1]][w2_r],
dp[i - 1][w1_r][w2_r]
);
}
else
{
dp[i][w1_r][w2_r] = dp[i - 1][w1_r][w2_r];
}
}
}
}
return dp[n][w1][w2];
}
const arr = [8, 2, 3];
const n = arr.length;
const w1 = 10, w2 = 3;
console.log(maxWeight(arr, n, w1, w2));
|
Time complexity: O(N*W1*W2)
Auxiliary Space: O(N*W1*W2))