给定n个物品的重量和价值,将这些物品放入容量为W的背包中,得到背包中的最大总值。换句话说,给定两个整数数组 val[0..n-1] 和 wt[0..n-1],它们分别表示与 n 个项目相关的值和权重。同样给定一个代表背包容量的整数 W,找出 val[] 的最大值子集,使得该子集的权重之和小于或等于 W。你不能破坏一个项目,要么选择完整的项目,要么不不选择它(0-1 属性)。
方法 1 :通过 Brute-Force 算法或穷举搜索递归。
方法:一个简单的解决方案是考虑项目的所有子集,并计算所有子集的总权重和价值。考虑总权重小于 W 的唯一子集。从所有这些子集中选择最大值子集。
最优子结构:要考虑项目的所有子集,每个项目可以有两种情况。
- 情况 1:该项目包含在最优子集中。
- 情况 2:该项目未包含在最优集合中。
因此,从“n”项中可以获得的最大值是以下两个值中的最大值。
- n-1 项和 W 权重(不包括第 n 项)得到的最大值。
- 第n个项目的值加上n-1个项目得到的最大值和W减去第n个项目(包括第n个项目)的权重。
如果’nth’ 项的权重大于’W’,则不能包括第n 项,情况1是唯一的可能性。
下面是上述方法的实现:
C++
/* A Naive recursive implementation of
0-1 Knapsack problem */
#include
using namespace std;
// A utility function that returns
// maximum of two integers
int max(int a, int b) { return (a > b) ? a : b; }
// Returns the maximum value that
// can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
// Base Case
if (n == 0 || W == 0)
return 0;
// If weight of the nth item is more
// than Knapsack capacity W, then
// this item cannot be included
// in the optimal solution
if (wt[n - 1] > W)
return knapSack(W, wt, val, n - 1);
// Return the maximum of two cases:
// (1) nth item included
// (2) not included
else
return max(
val[n - 1]
+ knapSack(W - wt[n - 1],
wt, val, n - 1),
knapSack(W, wt, val, n - 1));
}
// Driver code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
// This code is contributed by rathbhupendra
C
/* A Naive recursive implementation
of 0-1 Knapsack problem */
#include
// A utility function that returns
// maximum of two integers
int max(int a, int b) { return (a > b) ? a : b; }
// Returns the maximum value that can be
// put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
// Base Case
if (n == 0 || W == 0)
return 0;
// If weight of the nth item is more than
// Knapsack capacity W, then this item cannot
// be included in the optimal solution
if (wt[n - 1] > W)
return knapSack(W, wt, val, n - 1);
// Return the maximum of two cases:
// (1) nth item included
// (2) not included
else
return max(
val[n - 1]
+ knapSack(W - wt[n - 1],
wt, val, n - 1),
knapSack(W, wt, val, n - 1));
}
// Driver program to test above function
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
printf("%d", knapSack(W, wt, val, n));
return 0;
}
Java
/* A Naive recursive implementation
of 0-1 Knapsack problem */
class Knapsack {
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of
// capacity W
static int knapSack(int W, int wt[], int val[], int n)
{
// Base Case
if (n == 0 || W == 0)
return 0;
// If weight of the nth item is
// more than Knapsack capacity W,
// then this item cannot be included
// in the optimal solution
if (wt[n - 1] > W)
return knapSack(W, wt, val, n - 1);
// Return the maximum of two cases:
// (1) nth item included
// (2) not included
else
return max(val[n - 1]
+ knapSack(W - wt[n - 1], wt,
val, n - 1),
knapSack(W, wt, val, n - 1));
}
// Driver code
public static void main(String args[])
{
int val[] = new int[] { 60, 100, 120 };
int wt[] = new int[] { 10, 20, 30 };
int W = 50;
int n = val.length;
System.out.println(knapSack(W, wt, val, n));
}
}
/*This code is contributed by Rajat Mishra */
Python
# A naive recursive implementation
# of 0-1 Knapsack Problem
# Returns the maximum value that
# can be put in a knapsack of
# capacity W
def knapSack(W, wt, val, n):
# Base Case
if n == 0 or W == 0:
return 0
# If weight of the nth item is
# more than Knapsack of capacity W,
# then this item cannot be included
# in the optimal solution
if (wt[n-1] > W):
return knapSack(W, wt, val, n-1)
# return the maximum of two cases:
# (1) nth item included
# (2) not included
else:
return max(
val[n-1] + knapSack(
W-wt[n-1], wt, val, n-1),
knapSack(W, wt, val, n-1))
# end of function knapSack
#Driver Code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print knapSack(W, wt, val, n)
# This code is contributed by Nikhil Kumar Singh
C#
/* A Naive recursive implementation of
0-1 Knapsack problem */
using System;
class GFG {
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that can
// be put in a knapsack of capacity W
static int knapSack(int W, int[] wt,
int[] val, int n)
{
// Base Case
if (n == 0 || W == 0)
return 0;
// If weight of the nth item is
// more than Knapsack capacity W,
// then this item cannot be
// included in the optimal solution
if (wt[n - 1] > W)
return knapSack(W, wt,
val, n - 1);
// Return the maximum of two cases:
// (1) nth item included
// (2) not included
else
return max(val[n - 1]
+ knapSack(W - wt[n - 1], wt,
val, n - 1),
knapSack(W, wt, val, n - 1));
}
// Driver code
public static void Main()
{
int[] val = new int[] { 60, 100, 120 };
int[] wt = new int[] { 10, 20, 30 };
int W = 50;
int n = val.Length;
Console.WriteLine(knapSack(W, wt, val, n));
}
}
// This code is contributed by Sam007
PHP
$W)
return knapSack($W, $wt, $val, $n - 1);
// Return the maximum of two cases:
// (1) nth item included
// (2) not included
else
return max($val[$n - 1] +
knapSack($W - $wt[$n - 1],
$wt, $val, $n - 1),
knapSack($W, $wt, $val, $n-1));
}
// Driver Code
$val = array(60, 100, 120);
$wt = array(10, 20, 30);
$W = 50;
$n = count($val);
echo knapSack($W, $wt, $val, $n);
// This code is contributed by Sam007
?>
Javascript
C++
// A dynamic programming based
// solution for 0-1 Knapsack problem
#include
using namespace std;
// A utility function that returns
// maximum of two integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
int i, w;
vector> K(n + 1, vector(W + 1));
// Build table K[][] in bottom up manner
for(i = 0; i <= n; i++)
{
for(w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w] = max(val[i - 1] +
K[i - 1][w - wt[i - 1]],
K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
// Driver Code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
// This code is contributed by Debojyoti Mandal
C
// A Dynamic Programming based
// solution for 0-1 Knapsack problem
#include
// A utility function that returns
// maximum of two integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
int i, w;
int K[n + 1][W + 1];
// Build table K[][] in bottom up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w] = max(val[i - 1]
+ K[i - 1][w - wt[i - 1]],
K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
// Driver Code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
printf("%d", knapSack(W, wt, val, n));
return 0;
}
Java
// A Dynamic Programming based solution
// for 0-1 Knapsack problem
class Knapsack {
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that can
// be put in a knapsack of capacity W
static int knapSack(int W, int wt[],
int val[], int n)
{
int i, w;
int K[][] = new int[n + 1][W + 1];
// Build table K[][] in bottom up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w]
= max(val[i - 1]
+ K[i - 1][w - wt[i - 1]],
K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
// Driver code
public static void main(String args[])
{
int val[] = new int[] { 60, 100, 120 };
int wt[] = new int[] { 10, 20, 30 };
int W = 50;
int n = val.length;
System.out.println(knapSack(W, wt, val, n));
}
}
/*This code is contributed by Rajat Mishra */
Python
# A Dynamic Programming based Python
# Program for 0-1 Knapsack problem
# Returns the maximum value that can
# be put in a knapsack of capacity W
def knapSack(W, wt, val, n):
K = [[0 for x in range(W + 1)] for x in range(n + 1)]
# Build table K[][] in bottom up manner
for i in range(n + 1):
for w in range(W + 1):
if i == 0 or w == 0:
K[i][w] = 0
elif wt[i-1] <= w:
K[i][w] = max(val[i-1]
+ K[i-1][w-wt[i-1]],
K[i-1][w])
else:
K[i][w] = K[i-1][w]
return K[n][W]
# Driver code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print(knapSack(W, wt, val, n))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming based solution for
// 0-1 Knapsack problem
using System;
class GFG {
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of
// capacity W
static int knapSack(int W, int[] wt,
int[] val, int n)
{
int i, w;
int[, ] K = new int[n + 1, W + 1];
// Build table K[][] in bottom
// up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i, w] = 0;
else if (wt[i - 1] <= w)
K[i, w] = Math.Max(
val[i - 1]
+ K[i - 1, w - wt[i - 1]],
K[i - 1, w]);
else
K[i, w] = K[i - 1, w];
}
}
return K[n, W];
}
// Driver code
static void Main()
{
int[] val = new int[] { 60, 100, 120 };
int[] wt = new int[] { 10, 20, 30 };
int W = 50;
int n = val.Length;
Console.WriteLine(knapSack(W, wt, val, n));
}
}
// This code is contributed by Sam007
PHP
Javascript
C++
// Here is the top-down approach of
// dynamic programming
#include
using namespace std;
// Returns the value of maximum profit
int knapSackRec(int W, int wt[],
int val[], int i,
int** dp)
{
// base condition
if (i < 0)
return 0;
if (dp[i][W] != -1)
return dp[i][W];
if (wt[i] > W) {
// Store the value of function call
// stack in table before return
dp[i][W] = knapSackRec(W, wt,
val, i - 1,
dp);
return dp[i][W];
}
else {
// Store value in a table before return
dp[i][W] = max(val[i]
+ knapSackRec(W - wt[i],
wt, val,
i - 1, dp),
knapSackRec(W, wt, val,
i - 1, dp));
// Return value of table after storing
return dp[i][W];
}
}
int knapSack(int W, int wt[], int val[], int n)
{
// double pointer to declare the
// table dynamically
int** dp;
dp = new int*[n];
// loop to create the table dynamically
for (int i = 0; i < n; i++)
dp[i] = new int[W + 1];
// loop to initially filled the
// table with -1
for (int i = 0; i < n; i++)
for (int j = 0; j < W + 1; j++)
dp[i][j] = -1;
return knapSackRec(W, wt, val, n - 1, dp);
}
// Driver Code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
Java
// Here is the top-down approach of
// dynamic programming
class GFG{
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the value of maximum profit
static int knapSackRec(int W, int wt[],
int val[], int n,
int [][]dp)
{
// Base condition
if (n == 0 || W == 0)
return 0;
if (dp[n][W] != -1)
return dp[n][W];
if (wt[n - 1] > W)
// Store the value of function call
// stack in table before return
return dp[n][W] = knapSackRec(W, wt, val,
n - 1, dp);
else
// Return value of table after storing
return dp[n][W] = max((val[n - 1] +
knapSackRec(W - wt[n - 1], wt,
val, n - 1, dp)),
knapSackRec(W, wt, val,
n - 1, dp));
}
static int knapSack(int W, int wt[], int val[], int N)
{
// Declare the table dynamically
int dp[][] = new int[N + 1][W + 1];
// Loop to initially filled the
// table with -1
for(int i = 0; i < N + 1; i++)
for(int j = 0; j < W + 1; j++)
dp[i][j] = -1;
return knapSackRec(W, wt, val, N, dp);
}
// Driver Code
public static void main(String [] args)
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int N = val.length;
System.out.println(knapSack(W, wt, val, N));
}
}
// This Code is contributed By FARAZ AHMAD
Python3
# This is the memoization approach of
# 0 / 1 Knapsack in Python in simple
# we can say recursion + memoization = DP
# driver code
val = [60, 100, 120 ]
wt = [10, 20, 30 ]
W = 50
n = len(val)
# We initialize the matrix with -1 at first.
t = [[-1 for i in range(W + 1)] for j in range(n + 1)]
def knapsack(wt, val, W, n):
# base conditions
if n == 0 or W == 0:
return 0
if t[n][W] != -1:
return t[n][W]
# choice diagram code
if wt[n-1] <= W:
t[n][W] = max(
val[n-1] + knapsack(
wt, val, W-wt[n-1], n-1),
knapsack(wt, val, W, n-1))
return t[n][W]
elif wt[n-1] > W:
t[n][W] = knapsack(wt, val, W, n-1)
return t[n][W]
print(knapsack(wt, val, W, n))
# This code is contributed by Prosun Kumar Sarkar
C#
// Here is the top-down approach of
// dynamic programming
using System;
public class GFG
{
// A utility function that returns
// maximum of two integers
static int max(int a, int b) { return (a > b) ? a : b; }
// Returns the value of maximum profit
static int knapSackRec(int W, int[] wt, int[] val,
int n, int[, ] dp)
{
// Base condition
if (n == 0 || W == 0)
return 0;
if (dp[n, W] != -1)
return dp[n, W];
if (wt[n - 1] > W)
// Store the value of function call
// stack in table before return
return dp[n, W]
= knapSackRec(W, wt, val, n - 1, dp);
else
// Return value of table after storing
return dp[n, W]
= max((val[n - 1]
+ knapSackRec(W - wt[n - 1], wt, val,
n - 1, dp)),
knapSackRec(W, wt, val, n - 1, dp));
}
static int knapSack(int W, int[] wt, int[] val, int N)
{
// Declare the table dynamically
int[, ] dp = new int[N + 1, W + 1];
// Loop to initially filled the
// table with -1
for (int i = 0; i < N + 1; i++)
for (int j = 0; j < W + 1; j++)
dp[i, j] = -1;
return knapSackRec(W, wt, val, N, dp);
}
// Driver Code
static public void Main()
{
int[] val = new int[]{ 60, 100, 120 };
int[] wt = new int[]{ 10, 20, 30 };
int W = 50;
int N = val.Length;
Console.WriteLine(knapSack(W, wt, val, N));
}
}
// This Code is contributed By Dharanendra L V.
Javascript
Python3
# code
# A Dynamic Programming based Python
# Program for 0-1 Knapsack problem
# Returns the maximum value that can
# be put in a knapsack of capacity W
def knapSack(W, wt, val, n):
dp = [0 for i in range(W+1)] # Making the dp array
for i in range(1, n+1): # taking first i elements
for w in range(W, 0, -1): # starting from back,so that we also have data of
# previous computation when taking i-1 items
if wt[i-1] <= w:
# finding the maximum value
dp[w] = max(dp[w], dp[w-wt[i-1]]+val[i-1])
return dp[W] # returning the maximum value of knapsack
# Driver code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
# This code is contributed by Suyash Saxena
print(knapSack(W, wt, val, n))
C++
#include
using namespace std;
int knapSack(int W, int wt[], int val[], int n)
{
// making and initializing dp array
int dp[W + 1];
memset(dp, 0, sizeof(dp));
for (int i = 1; i < n + 1; i++) {
for (int w = W; w >= 0; w--) {
if (wt[i - 1] <= w)
// finding the maximum value
dp[w] = max(dp[w],
dp[w - wt[i - 1]] + val[i - 1]);
}
}
return dp[W]; // returning the maximum value of knapsack
}
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
220
需要注意的是,上述函数一次又一次地计算相同的子问题。请参阅以下递归树,K(1, 1) 被评估两次。这个朴素的递归解决方案的时间复杂度是指数级的 (2^n)。
In the following recursion tree, K() refers
to knapSack(). The two parameters indicated in the
following recursion tree are n and W.
The recursion tree is for following sample inputs.
wt[] = {1, 1, 1}, W = 2, val[] = {10, 20, 30}
K(n, W)
K(3, 2)
/ \
/ \
K(2, 2) K(2, 1)
/ \ / \
/ \ / \
K(1, 2) K(1, 1) K(1, 1) K(1, 0)
/ \ / \ / \
/ \ / \ / \
K(0, 2) K(0, 1) K(0, 1) K(0, 0) K(0, 1) K(0, 0)
Recursion tree for Knapsack capacity 2
units and 3 items of 1 unit weight.
复杂度分析:
- 时间复杂度: O(2 n )。
因为有多余的子问题。 - 辅助空间: O(1)。
因为没有使用额外的数据结构来存储值。
由于再次评估子问题,因此该问题具有重叠子问题的属性。所以 0-1 背包问题具有动态规划问题的两个性质(见这个和这个)。
方法2 :与其他典型的动态规划(DP)问题一样,通过自底向上构造临时数组K[][]可以避免相同子问题的重新计算。以下是基于动态规划的实现。
方法:在动态编程中,我们将考虑与递归方法中提到的相同的情况。在 DP[][] 表中,让我们考虑从“1”到“W”的所有可能权重作为列,权重可以保留为行。
状态 DP[i][j] 将表示考虑从“1”到“i”的所有值的“j-weight”的最大值。因此,如果我们考虑 ‘wi’(’ith’ 行中的权重),我们可以将其填充到所有具有 ‘weight values > wi’ 的列中。现在有两种可能:
- 在给定的列中填写“wi”。
- 不要在给定的列中填写“wi”。
现在我们必须取这两种可能性中的最大值,如果我们不在 ‘jth’ 列中填充 ‘ith’ 权重,那么 DP[i][j] 状态将与 DP[i-1][j] 相同,但是如果我们填充权重,DP[i][j] 将等于 ‘wi’ 的值 + 前一行中权重为 ‘j-wi’ 的列的值。所以我们取这两种可能性中的最大值来填充当前状态。此可视化将使概念清晰:
Let weight elements = {1, 2, 3}
Let weight values = {10, 15, 40}
Capacity=6
0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 10 10 10 10 10 10
2 0 10 15 25 25 25 25
3 0
Explanation:
For filling 'weight = 2' we come
across 'j = 3' in which
we take maximum of
(10, 15 + DP[1][3-2]) = 25
| |
'2' '2 filled'
not filled
0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 10 10 10 10 10 10
2 0 10 15 25 25 25 25
3 0 10 15 40 50 55 65
Explanation:
For filling 'weight=3',
we come across 'j=4' in which
we take maximum of (25, 40 + DP[2][4-3])
= 50
For filling 'weight=3'
we come across 'j=5' in which
we take maximum of (25, 40 + DP[2][5-3])
= 55
For filling 'weight=3'
we come across 'j=6' in which
we take maximum of (25, 40 + DP[2][6-3])
= 65
C++
// A dynamic programming based
// solution for 0-1 Knapsack problem
#include
using namespace std;
// A utility function that returns
// maximum of two integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
int i, w;
vector> K(n + 1, vector(W + 1));
// Build table K[][] in bottom up manner
for(i = 0; i <= n; i++)
{
for(w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w] = max(val[i - 1] +
K[i - 1][w - wt[i - 1]],
K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
// Driver Code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
// This code is contributed by Debojyoti Mandal
C
// A Dynamic Programming based
// solution for 0-1 Knapsack problem
#include
// A utility function that returns
// maximum of two integers
int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of capacity W
int knapSack(int W, int wt[], int val[], int n)
{
int i, w;
int K[n + 1][W + 1];
// Build table K[][] in bottom up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w] = max(val[i - 1]
+ K[i - 1][w - wt[i - 1]],
K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
// Driver Code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
printf("%d", knapSack(W, wt, val, n));
return 0;
}
Java
// A Dynamic Programming based solution
// for 0-1 Knapsack problem
class Knapsack {
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that can
// be put in a knapsack of capacity W
static int knapSack(int W, int wt[],
int val[], int n)
{
int i, w;
int K[][] = new int[n + 1][W + 1];
// Build table K[][] in bottom up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w]
= max(val[i - 1]
+ K[i - 1][w - wt[i - 1]],
K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
// Driver code
public static void main(String args[])
{
int val[] = new int[] { 60, 100, 120 };
int wt[] = new int[] { 10, 20, 30 };
int W = 50;
int n = val.length;
System.out.println(knapSack(W, wt, val, n));
}
}
/*This code is contributed by Rajat Mishra */
Python
# A Dynamic Programming based Python
# Program for 0-1 Knapsack problem
# Returns the maximum value that can
# be put in a knapsack of capacity W
def knapSack(W, wt, val, n):
K = [[0 for x in range(W + 1)] for x in range(n + 1)]
# Build table K[][] in bottom up manner
for i in range(n + 1):
for w in range(W + 1):
if i == 0 or w == 0:
K[i][w] = 0
elif wt[i-1] <= w:
K[i][w] = max(val[i-1]
+ K[i-1][w-wt[i-1]],
K[i-1][w])
else:
K[i][w] = K[i-1][w]
return K[n][W]
# Driver code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print(knapSack(W, wt, val, n))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming based solution for
// 0-1 Knapsack problem
using System;
class GFG {
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of
// capacity W
static int knapSack(int W, int[] wt,
int[] val, int n)
{
int i, w;
int[, ] K = new int[n + 1, W + 1];
// Build table K[][] in bottom
// up manner
for (i = 0; i <= n; i++)
{
for (w = 0; w <= W; w++)
{
if (i == 0 || w == 0)
K[i, w] = 0;
else if (wt[i - 1] <= w)
K[i, w] = Math.Max(
val[i - 1]
+ K[i - 1, w - wt[i - 1]],
K[i - 1, w]);
else
K[i, w] = K[i - 1, w];
}
}
return K[n, W];
}
// Driver code
static void Main()
{
int[] val = new int[] { 60, 100, 120 };
int[] wt = new int[] { 10, 20, 30 };
int W = 50;
int n = val.Length;
Console.WriteLine(knapSack(W, wt, val, n));
}
}
// This code is contributed by Sam007
PHP
Javascript
220
复杂度分析:
- 时间复杂度: O(N*W)。
其中“N”是权重元素的数量,“W”是容量。对于每个权重元素,我们遍历所有权重容量 1<=w<=W。 - 辅助空间: O(N*W)。
使用大小为“N*W”的二维数组。
方法 3 :此方法使用 Memoization Technique(递归方法的扩展)。
这种方法基本上是递归方法的扩展,因此我们可以克服计算冗余案例从而增加复杂性的问题。我们可以通过简单地创建一个二维数组来解决这个问题,如果我们第一次得到它,它可以存储一个特定的状态 (n, w)。现在,如果我们再次遇到相同的状态 (n, w) 而不是以指数复杂度计算它,我们可以在恒定时间内直接返回其存储在表中的结果。这种方法在这方面优于递归方法。
C++
// Here is the top-down approach of
// dynamic programming
#include
using namespace std;
// Returns the value of maximum profit
int knapSackRec(int W, int wt[],
int val[], int i,
int** dp)
{
// base condition
if (i < 0)
return 0;
if (dp[i][W] != -1)
return dp[i][W];
if (wt[i] > W) {
// Store the value of function call
// stack in table before return
dp[i][W] = knapSackRec(W, wt,
val, i - 1,
dp);
return dp[i][W];
}
else {
// Store value in a table before return
dp[i][W] = max(val[i]
+ knapSackRec(W - wt[i],
wt, val,
i - 1, dp),
knapSackRec(W, wt, val,
i - 1, dp));
// Return value of table after storing
return dp[i][W];
}
}
int knapSack(int W, int wt[], int val[], int n)
{
// double pointer to declare the
// table dynamically
int** dp;
dp = new int*[n];
// loop to create the table dynamically
for (int i = 0; i < n; i++)
dp[i] = new int[W + 1];
// loop to initially filled the
// table with -1
for (int i = 0; i < n; i++)
for (int j = 0; j < W + 1; j++)
dp[i][j] = -1;
return knapSackRec(W, wt, val, n - 1, dp);
}
// Driver Code
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
Java
// Here is the top-down approach of
// dynamic programming
class GFG{
// A utility function that returns
// maximum of two integers
static int max(int a, int b)
{
return (a > b) ? a : b;
}
// Returns the value of maximum profit
static int knapSackRec(int W, int wt[],
int val[], int n,
int [][]dp)
{
// Base condition
if (n == 0 || W == 0)
return 0;
if (dp[n][W] != -1)
return dp[n][W];
if (wt[n - 1] > W)
// Store the value of function call
// stack in table before return
return dp[n][W] = knapSackRec(W, wt, val,
n - 1, dp);
else
// Return value of table after storing
return dp[n][W] = max((val[n - 1] +
knapSackRec(W - wt[n - 1], wt,
val, n - 1, dp)),
knapSackRec(W, wt, val,
n - 1, dp));
}
static int knapSack(int W, int wt[], int val[], int N)
{
// Declare the table dynamically
int dp[][] = new int[N + 1][W + 1];
// Loop to initially filled the
// table with -1
for(int i = 0; i < N + 1; i++)
for(int j = 0; j < W + 1; j++)
dp[i][j] = -1;
return knapSackRec(W, wt, val, N, dp);
}
// Driver Code
public static void main(String [] args)
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int N = val.length;
System.out.println(knapSack(W, wt, val, N));
}
}
// This Code is contributed By FARAZ AHMAD
蟒蛇3
# This is the memoization approach of
# 0 / 1 Knapsack in Python in simple
# we can say recursion + memoization = DP
# driver code
val = [60, 100, 120 ]
wt = [10, 20, 30 ]
W = 50
n = len(val)
# We initialize the matrix with -1 at first.
t = [[-1 for i in range(W + 1)] for j in range(n + 1)]
def knapsack(wt, val, W, n):
# base conditions
if n == 0 or W == 0:
return 0
if t[n][W] != -1:
return t[n][W]
# choice diagram code
if wt[n-1] <= W:
t[n][W] = max(
val[n-1] + knapsack(
wt, val, W-wt[n-1], n-1),
knapsack(wt, val, W, n-1))
return t[n][W]
elif wt[n-1] > W:
t[n][W] = knapsack(wt, val, W, n-1)
return t[n][W]
print(knapsack(wt, val, W, n))
# This code is contributed by Prosun Kumar Sarkar
C#
// Here is the top-down approach of
// dynamic programming
using System;
public class GFG
{
// A utility function that returns
// maximum of two integers
static int max(int a, int b) { return (a > b) ? a : b; }
// Returns the value of maximum profit
static int knapSackRec(int W, int[] wt, int[] val,
int n, int[, ] dp)
{
// Base condition
if (n == 0 || W == 0)
return 0;
if (dp[n, W] != -1)
return dp[n, W];
if (wt[n - 1] > W)
// Store the value of function call
// stack in table before return
return dp[n, W]
= knapSackRec(W, wt, val, n - 1, dp);
else
// Return value of table after storing
return dp[n, W]
= max((val[n - 1]
+ knapSackRec(W - wt[n - 1], wt, val,
n - 1, dp)),
knapSackRec(W, wt, val, n - 1, dp));
}
static int knapSack(int W, int[] wt, int[] val, int N)
{
// Declare the table dynamically
int[, ] dp = new int[N + 1, W + 1];
// Loop to initially filled the
// table with -1
for (int i = 0; i < N + 1; i++)
for (int j = 0; j < W + 1; j++)
dp[i, j] = -1;
return knapSackRec(W, wt, val, N, dp);
}
// Driver Code
static public void Main()
{
int[] val = new int[]{ 60, 100, 120 };
int[] wt = new int[]{ 10, 20, 30 };
int W = 50;
int N = val.Length;
Console.WriteLine(knapSack(W, wt, val, N));
}
}
// This Code is contributed By Dharanendra L V.
Javascript
220
复杂度分析:
- 时间复杂度: O(N*W)。
因为避免了状态的冗余计算。 - 辅助空间: O(N*W)。
使用二维数组数据结构存储中间状态-:
[注意:对于 32 位整数,请使用 long 而不是 int。]
参考:
- http://www.es.ele.tue.nl/education/5MC10/Solutions/knapsack.pdf
- http://www.cse.unl.edu/~goddard/Courses/CSCE310J/Lectures/Lecture8-DynamicProgramming.pdf
方法 4:-我们使用动态规划方法,但具有优化的空间复杂度。
蟒蛇3
# code
# A Dynamic Programming based Python
# Program for 0-1 Knapsack problem
# Returns the maximum value that can
# be put in a knapsack of capacity W
def knapSack(W, wt, val, n):
dp = [0 for i in range(W+1)] # Making the dp array
for i in range(1, n+1): # taking first i elements
for w in range(W, 0, -1): # starting from back,so that we also have data of
# previous computation when taking i-1 items
if wt[i-1] <= w:
# finding the maximum value
dp[w] = max(dp[w], dp[w-wt[i-1]]+val[i-1])
return dp[W] # returning the maximum value of knapsack
# Driver code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
# This code is contributed by Suyash Saxena
print(knapSack(W, wt, val, n))
C++
#include
using namespace std;
int knapSack(int W, int wt[], int val[], int n)
{
// making and initializing dp array
int dp[W + 1];
memset(dp, 0, sizeof(dp));
for (int i = 1; i < n + 1; i++) {
for (int w = W; w >= 0; w--) {
if (wt[i - 1] <= w)
// finding the maximum value
dp[w] = max(dp[w],
dp[w - wt[i - 1]] + val[i - 1]);
}
}
return dp[W]; // returning the maximum value of knapsack
}
int main()
{
int val[] = { 60, 100, 120 };
int wt[] = { 10, 20, 30 };
int W = 50;
int n = sizeof(val) / sizeof(val[0]);
cout << knapSack(W, wt, val, n);
return 0;
}
220
复杂性分析:
时间复杂度:O(N*W)。因为避免了状态的冗余计算。
辅助空间:O(W) 因为我们使用的是一维数组而不是二维数组。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。