Given the 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. We cannot break an item, either pick the complete item or don’t pick it (0-1 property).
Here W <= 2000000 and n <= 500
Examples:
Input: W = 10, n = 3
val[] = {7, 8, 4}
wt[] = {3, 8, 6}
Output: 11
Explanation: We get maximum value by picking items of 3 KG and 6 KG.
We have discussed a Dynamic Programming based solution here. In the previous solution, we used a n * W matrix. We can reduce the used extra space. The idea behind the optimization is, to compute mat[i][j], we only need solution of previous row. In 0-1 Knapsack Problem if we are currently on mat[i][j] and we include ith element then we move j-wt[i] steps back in previous row and if we exclude the current element we move on jth column in the previous row. So here we can observe that at a time we are working only with 2 consecutive rows.
In the below solution, we create a matrix of size 2*W. If n is odd, then the final answer will be at mat[0][W] and if n is even then the final answer will be at mat[1][W] because index starts from 0.
C++
#include<bits/stdc++.h>
using namespace std;
int KnapSack( int val[], int wt[], int n, int W)
{
int mat[2][W+1];
memset (mat, 0, sizeof (mat));
int i = 0;
while (i < n)
{
int j = 0;
if (i%2!=0)
{
while (++j <= W)
{
if (wt[i] <= j)
mat[1][j] = max(val[i] + mat[0][j-wt[i]],
mat[0][j] );
else
mat[1][j] = mat[0][j];
}
}
else
{
while (++j <= W)
{
if (wt[i] <= j)
mat[0][j] = max(val[i] + mat[1][j-wt[i]],
mat[1][j]);
else
mat[0][j] = mat[1][j];
}
}
i++;
}
return (n%2 != 0)? mat[0][W] : mat[1][W];
}
int main()
{
int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
cout << KnapSack(val, wt, n, W) << endl;
return 0;
}
|
Java
class GFG
{
static int KnapSack( int val[], int wt[],
int n, int W)
{
int mat[][] = new int [ 2 ][W + 1 ];
int i = 0 ;
while (i < n)
{
int j = 0 ;
if (i % 2 != 0 )
{
while (++j <= W)
{
if (wt[i] <= j)
{
mat[ 1 ][j] = Math.max(val[i] + mat[ 0 ][j - wt[i]],
mat[ 0 ][j]);
} else
{
mat[ 1 ][j] = mat[ 0 ][j];
}
}
}
else
{
while (++j <= W)
{
if (wt[i] <= j)
{
mat[ 0 ][j] = Math.max(val[i] + mat[ 1 ][j - wt[i]],
mat[ 1 ][j]);
} else
{
mat[ 0 ][j] = mat[ 1 ][j];
}
}
}
i++;
}
return (n % 2 != 0 ) ? mat[ 0 ][W] : mat[ 1 ][W];
}
public static void main(String[] args)
{
int val[] = { 7 , 8 , 4 },
wt[] = { 3 , 8 , 6 },
W = 10 , n = 3 ;
System.out.println(KnapSack(val, wt, n, W));
}
}
|
Python3
def KnapSack(val, wt, n, W):
mat = [[ 0 for i in range (W + 1 )]
for i in range ( 2 )]
i = 0
while i < n:
j = 0
if i % 2 = = 0 :
while j < W:
j + = 1
if wt[i] < = j:
mat[ 1 ][j] = max (val[i] + mat[ 0 ][j -
wt[i]], mat[ 0 ][j])
else :
mat[ 1 ][j] = mat[ 0 ][j]
else :
while j < W:
j + = 1
if wt[i] < = j:
mat[ 0 ][j] = max (val[i] + mat[ 1 ][j -
wt[i]], mat[ 1 ][j])
else :
mat[ 0 ][j] = mat[ 1 ][j]
i + = 1
if n % 2 = = 0 :
return mat[ 0 ][W]
else :
return mat[ 1 ][W]
val = [ 7 , 8 , 4 ]
wt = [ 3 , 8 , 6 ]
W = 10
n = 3
print (KnapSack(val, wt, n, W))
|
C#
using System;
class GFG
{
static int KnapSack( int []val, int []wt,
int n, int W)
{
int [,]mat = new int [2, W + 1];
int i = 0;
while (i < n)
{
int j = 0;
if (i % 2 != 0)
{
while (++j <= W)
{
if (wt[i] <= j)
{
mat[1, j] = Math.Max(val[i] + mat[0, j - wt[i]],
mat[0, j]);
} else
{
mat[1,j] = mat[0,j];
}
}
}
else
{
while (++j <= W)
{
if (wt[i] <= j)
{
mat[0, j] = Math.Max(val[i] + mat[1, j - wt[i]],
mat[1, j]);
}
else
{
mat[0, j] = mat[1, j];
}
}
}
i++;
}
return (n % 2 != 0) ? mat[0, W] : mat[1, W];
}
public static void Main(String[] args)
{
int []val = {7, 8, 4};
int []wt = {3, 8, 6};
int W = 10, n = 3;
Console.WriteLine(KnapSack(val, wt, n, W));
}
}
|
PHP
<?php
function KnapSack(& $val , & $wt , $n , $W )
{
$mat = array_fill (0, 2,
array_fill (0, $W + 1, NULL));
$i = 0;
while ( $i < $n )
{
$j = 0;
if ( $i % 2 != 0)
{
while (++ $j <= $W )
{
if ( $wt [ $i ] <= $j )
$mat [1][ $j ] = max( $val [ $i ] + $mat [0][ $j -
$wt [ $i ]], $mat [0][ $j ]);
else
$mat [1][ $j ] = $mat [0][ $j ];
}
}
else
{
while (++ $j <= $W )
{
if ( $wt [ $i ] <= $j )
$mat [0][ $j ] = max( $val [ $i ] + $mat [1][ $j -
$wt [ $i ]], $mat [1][ $j ]);
else
$mat [0][ $j ] = $mat [1][ $j ];
}
}
$i ++;
}
if ( $n % 2 != 0)
return $mat [0][ $W ];
else
return $mat [1][ $W ];
}
$val = array (7, 8, 4);
$wt = array (3, 8, 6);
$W = 10;
$n = 3;
echo KnapSack( $val , $wt , $n , $W ) . "\n" ;
?>
|
Javascript
<script>
function KnapSack(val, wt, n, W)
{
let mat = new Array(2);
for (let i = 0; i < 2; i++)
{
mat[i] = new Array(W + 1);
}
for (let i = 0; i < 2; i++)
{
for (let j = 0; j < W + 1; j++)
{
mat[i][j] = 0;
}
}
let i = 0;
while (i < n)
{
let j = 0;
if (i % 2 != 0)
{
while (++j <= W)
{
if (wt[i] <= j)
{
mat[1][j] = Math.max(val[i] + mat[0][j - wt[i]],
mat[0][j]);
} else
{
mat[1][j] = mat[0][j];
}
}
}
else
{
while (++j <= W)
{
if (wt[i] <= j)
{
mat[0][j] = Math.max(val[i] + mat[1][j - wt[i]],
mat[1][j]);
} else
{
mat[0][j] = mat[1][j];
}
}
}
i++;
}
return (n % 2 != 0) ? mat[0][W] : mat[1][W];
}
let val=[7, 8, 4];
let wt=[3, 8, 6];
let W = 10, n = 3;
document.write(KnapSack(val, wt, n, W));
</script>
|
Time Complexity: O(n * W)
Auxiliary Space: O(W)
Here is an optimized code contributed by Gaurav Mamgain
C++14
#include <bits/stdc++.h>
using namespace std;
int KnapSack( int val[], int wt[], int n, int W)
{
int dp[W + 1];
memset (dp, 0, sizeof (dp));
for ( int i = 0; i < n; i++)
for ( int j = W; j >= wt[i]; j--)
dp[j] = max(dp[j], val[i] + dp[j - wt[i]]);
return dp[W];
}
int main()
{
int val[] = { 7, 8, 4 }, wt[] = { 3, 8, 6 }, W = 10,
n = 3;
cout << KnapSack(val, wt, n, W) << endl;
return 0;
}
|
Java
import java.util.Arrays;
class GFG
{
static int KnapSack( int val[], int wt[], int n, int W)
{
int []dp = new int [W+ 1 ];
Arrays.fill(dp, 0 );
for ( int i= 0 ; i < n; i++)
for ( int j = W; j >= wt[i]; j--)
dp[j] = Math.max(dp[j] , val[i] + dp[j - wt[i]]);
return dp[W];
}
public static void main(String[] args)
{
int val[] = { 7 , 8 , 4 }, wt[] = { 3 , 8 , 6 }, W = 10 , n = 3 ;
System.out.println(KnapSack(val, wt, n, W));
}
}
|
Python3
def KnapSack(val, wt, n, W):
dp = [ 0 ] * (W + 1 );
for i in range (n):
for j in range (W,wt[i] - 1 , - 1 ):
dp[j] = max (dp[j] , val[i] + dp[j - wt[i]]);
return dp[W];
val = [ 7 , 8 , 4 ];
wt = [ 3 , 8 , 6 ];
W = 10 ; n = 3 ;
print (KnapSack(val, wt, n, W));
|
C#
using System;
class GFG
{
static int KnapSack( int []val, int []wt, int n, int W)
{
int []dp = new int [W + 1];
for ( int i = 0; i < W + 1; i++)
dp[i] = 0;
for ( int i = 0; i < n; i++)
for ( int j = W; j >= wt[i]; j--)
dp[j] = Math.Max(dp[j] , val[i] + dp[j - wt[i]]);
return dp[W];
}
public static void Main(String[] args)
{
int []val = {7, 8, 4};
int []wt = {3, 8, 6};
int W = 10, n = 3;
Console.WriteLine(KnapSack(val, wt, n, W));
}
}
|
Javascript
<script>
function KnapSack(val,wt,n,W)
{
let dp = new Array(W+1);
for (let i=0;i<W+1;i++)
{
dp[i]=0;
}
for (let i=0; i < n; i++)
for (let j = W; j >= wt[i]; j--)
dp[j] = Math.max(dp[j] , val[i] + dp[j - wt[i]]);
return dp[W];
}
let val=[7, 8, 4];
let wt=[3, 8, 6];
let W = 10, n = 3;
document.write(KnapSack(val, wt, n, W));
</script>
|
Time complexity: O(n * W)
Auxiliary space: O(W)
This article is contributed by Shashank Mishra ( Gullu ). This article is reviewed by team geeksforgeeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.