📜  扩展背包问题

📅  最后修改于: 2021-04-24 20:21:11             🧑  作者: 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


输出:
12







时间复杂度: O(N * W * K)
辅助空间: O(N * W * K)