📜  扩展背包问题

📅  最后修改于: 2021-10-26 05:09:16             🧑  作者: Mango

给定N 个项目,每个项目具有给定的权重C i和利润值P i ,任务是通过选择最多K 个项目加起来最大权重W来最大化利润。

例子:

方法:动态规划方法优于一般递归方法。我们先验证一下DP的条件还是满足的。

  1. 重叠子问题:递归求解时,先加1项,解集为(1),(2),…(n)。在第二次迭代中,我们有 (1, 2) 等等,其中 (1) 和 (2) 被重新计算。因此会有重叠的解决方案。
  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] ,利润要么是前一个状态的利润(当当前状态不包括在内)或当前项目的利润添加到前一个状态的利润(当当前状态项被选中)。因此,递推关系为:

下面是上述方法的实现:

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 现场工作专业课程学生竞争性编程现场课程