给定N 个项目,每个项目具有给定的权重C i和利润值P i ,任务是通过选择最多K 个项目加起来最大权重W来最大化利润。
例子:
Input: N = 5, P[] = {2, 7, 1, 5, 3}, C[] = {2, 5, 2, 3, 4}, W = 8, K = 2.
Output: 12
Explanation:
Here, the maximum possible profit is when we take 2 items: item2 (P[1] = 7 and C[1] = 5) and item4 (P[3] = 5 and C[3] = 3).
Hence, maximum profit = 7 + 5 = 12
Input: N = 5, P[] = {2, 7, 1, 5, 3}, C[] = {2, 5, 2, 3, 4}, W = 1, K = 2
Output: 0
Explanation: All weights are greater than 1. Hence, no item can be picked.
方法:动态规划方法优于一般递归方法。我们先验证DP的条件还是满足的。
- 重叠子问题:尝试递归求解时,先添加1项,求解集为(1)、(2)、……(n)。在第二次迭代中,我们有 (1, 2) 等等,其中 (1) 和 (2) 被重新计算。因此会有重叠的解决方案。
- 最优子结构:总体而言,每个项目只有两个选择,要么可以包含在解决方案中,要么可以拒绝。对于特定的 z 个元素子集,第 (z+1)个元素的解可以有对应于 z 个元素的解,或者如果第 (z+1)个元素不超过背包约束,则可以添加第(z+1)个元素。无论哪种方式,都满足最优子结构属性。
让我们推导出递归。让我们考虑一个 3 维表dp[N][W][K] ,其中N是元素的数量, W是最大承重能力, K是背包中允许的最大物品数量。让我们定义一个状态dp[i][j][k]其中i表示我们正在考虑第i个元素, j表示当前填充的权重, k表示到目前为止填充的项目数。
对于每个状态dp[i][j][k] ,利润要么是前一个状态的利润(当当前状态不包括在内)或当前项目的利润添加到前一个状态的利润(当当前状态项被选中)。因此,递推关系为:
dp[i][j][k] = max( dp[i-1][j][k], dp[i-1][j-W[i-1]][k-1] + P[i])
下面是上述方法的实现:
C++
// C++ code for the extended
// Knapsack Approach
#include
using namespace std;
// To store the dp values
int dp[100][100][100];
int maxProfit(int profit[],
int weight[],
int n, int max_W,
int max_E)
{
// for each element given
for (int i = 1; i <= n; i++)
{
// For each possible
// weight value
for (int j = 1; j <= max_W; j++)
{
// For each case where
// the total elements are
// less than the constraint
for (int k = 1; k <= max_E; k++)
{
// To ensure that we dont
// go out of the array
if (j >= weight[i-1])
{
dp[i][j][k]
= max(dp[i - 1][j][k],
dp[i - 1][j -
weight[i-1]][k - 1]+
profit[i-1]);
}
else
{
dp[i][j][k]
= dp[i - 1][j][k];
}
}
}
}
return dp[n][max_W][max_E];
}
// Driver Code
int main()
{
memset(dp, 0, sizeof(dp));
int n = 5;
int profit[] = { 2, 7, 1, 5, 3 };
int weight[] = { 2, 5, 2, 3, 4 };
int max_weight = 8;
int max_element = 2;
cout << maxProfit(profit,
weight, n,
max_weight,
max_element)
<< "\n";
return 0;
}
Java
// Java code for the extended
// Knapsack Approach
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG{
// To store the dp values
static int[][][] dp = new int[100][100][100];
static int maxProfit(int profit[],
int weight[],
int n, int max_W,
int max_E)
{
// for each element given
for(int i = 1; i <= n; i++)
{
// For each possible
// weight value
for(int j = 1; j <= max_W; j++)
{
// For each case where
// the total elements are
// less than the constraint
for(int k = 1; k <= max_E; k++)
{
// To ensure that we dont
// go out of the array
if (j >= weight[i - 1])
{
dp[i][j][k] = Math.max(dp[i - 1][j][k],
dp[i - 1][j -
weight[i - 1]][k - 1] +
profit[i - 1]);
}
else
{
dp[i][j][k] = dp[i - 1][j][k];
}
}
}
}
return dp[n][max_W][max_E];
}
// Driver code
public static void main(String[] args)
{
int n = 5;
int profit[] = { 2, 7, 1, 5, 3 };
int weight[] = { 2, 5, 2, 3, 4 };
int max_weight = 8;
int max_element = 2;
System.out.println(maxProfit(profit,
weight, n,
max_weight,
max_element));
}
}
// This code is contributed by offbeat
Javascript
12
时间复杂度: O(N * W * K)
辅助空间: O(N * W * K)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。