给定一个包含’N’个不同项目的权重的数组’arr’,以及两个可以承受’W1’和’W2’权重的背包,任务是找到该数组’arr’的最大子集的总和,即可以放在两个背包中。不允许将任何物品一分为二,即应将一个物品作为一个整体放在一个袋子中。
例子:
Input : arr[] = {8, 3, 2}
W1 = 10, W2 = 3
Output : 13
First and third objects go in the first knapsack. The second object goes in the second knapsack. Thus, the total weight becomes 13.
Input : arr[] = {8, 5, 3}
W1 = 10, W2 = 3
Output : 11
解决方案:
递归解决方案是尝试填充两个背包的所有可能方式,然后选择重量最大的背包。
为了优化上述思路,我们需要确定DP的状态,并以此为基础建立解决方案。经过很少的观察,我们可以确定这可以用三种状态(i,w1_r,w2_r)表示。这里的“ i”表示我们要存储的元素的索引,w1_r表示第一个背包的剩余空间,w2_r表示第二个背包的剩余空间。因此,可以使用具有递归关系的3维动态编程来解决该问题。
DP[i][w1_r][w2_r] = max( DP[i + 1][w1_r][w2_r],
arr[i] + DP[i + 1][w1_r - arr[i]][w2_r],
arr[i] + DP[i + 1][w1_r][w2_r - arr[i]])
上述递归关系的解释如下:
For each ‘i’, we can either:
- Don’t select the item ‘i’.
- Fill the item ‘i’ in first knapsack.
- Fill the item ‘i’ in second knapsack.
下面是上述方法的实现:
C++
// C++ implementation of the above approach
#include
#define maxN 31
#define maxW 31
using namespace std;
// 3D array to store
// states of DP
int dp[maxN][maxW][maxW];
// w1_r represents remaining capacity of 1st knapsack
// w2_r represents remaining capacity of 2nd knapsack
// i represents index of the array arr we are working on
int maxWeight(int* arr, int n, int w1_r, int w2_r, int i)
{
// Base case
if (i == n)
return 0;
if (dp[i][w1_r][w2_r] != -1)
return dp[i][w1_r][w2_r];
// Variables to store the result of three
// parts of recurrence relation
int fill_w1 = 0, fill_w2 = 0, fill_none = 0;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i], w2_r, i + 1);
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r - arr[i], i + 1);
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1);
// Store the state in the 3D array
dp[i][w1_r][w2_r] = max(fill_none, max(fill_w1, fill_w2));
return dp[i][w1_r][w2_r];
}
// Driver code
int main()
{
// Input array
int arr[] = { 8, 2, 3 };
// Initializing the array with -1
memset(dp, -1, sizeof(dp));
// Number of elements in the array
int n = sizeof(arr) / sizeof(arr[0]);
// Capacity of knapsacks
int w1 = 10, w2 = 3;
// Function to be called
cout << maxWeight(arr, n, w1, w2, 0);
return 0;
}
Java
// Java implementation of the above approach
class GFG
{
static int maxN = 31;
static int maxW = 31;
// 3D array to store
// states of DP
static int dp [][][] = new int[maxN][maxW][maxW];
// w1_r represents remaining capacity of 1st knapsack
// w2_r represents remaining capacity of 2nd knapsack
// i represents index of the array arr we are working on
static int maxWeight(int arr [] , int n, int w1_r, int w2_r, int i)
{
// Base case
if (i == n)
return 0;
if (dp[i][w1_r][w2_r] != -1)
return dp[i][w1_r][w2_r];
// Variables to store the result of three
// parts of recurrence relation
int fill_w1 = 0, fill_w2 = 0, fill_none = 0;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i], w2_r, i + 1);
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r - arr[i], i + 1);
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1);
// Store the state in the 3D array
dp[i][w1_r][w2_r] = Math.max(fill_none, Math.max(fill_w1, fill_w2));
return dp[i][w1_r][w2_r];
}
// Driver code
public static void main (String[] args)
{
// Input array
int arr[] = { 8, 2, 3 };
// Initializing the array with -1
for (int i = 0; i < maxN ; i++)
for (int j = 0; j < maxW ; j++)
for (int k = 0; k < maxW ; k++)
dp[i][j][k] = -1;
// Number of elements in the array
int n = arr.length;
// Capacity of knapsacks
int w1 = 10, w2 = 3;
// Function to be called
System.out.println(maxWeight(arr, n, w1, w2, 0));
}
}
// This code is contributed by ihritik
Python3
# Python3 implementation of the above approach
# w1_r represents remaining capacity of 1st knapsack
# w2_r represents remaining capacity of 2nd knapsack
# i represents index of the array arr we are working on
def maxWeight(arr, n, w1_r, w2_r, i):
# Base case
if i == n:
return 0
if dp[i][w1_r][w2_r] != -1:
return dp[i][w1_r][w2_r]
# Variables to store the result of three
# parts of recurrence relation
fill_w1, fill_w2, fill_none = 0, 0, 0
if w1_r >= arr[i]:
fill_w1 = arr[i] + maxWeight(arr, n, w1_r - arr[i],
w2_r, i + 1)
if w2_r >= arr[i]:
fill_w2 = arr[i] + maxWeight(arr, n, w1_r,
w2_r - arr[i], i + 1)
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1)
# Store the state in the 3D array
dp[i][w1_r][w2_r] = max(fill_none, max(fill_w1,
fill_w2))
return dp[i][w1_r][w2_r]
# Driver code
if __name__ == "__main__":
# Input array
arr = [8, 2, 3]
maxN, maxW = 31, 31
# 3D array to store
# states of DP
dp = [[[-1] * maxW] * maxW] * maxN
# Number of elements in the array
n = len(arr)
# Capacity of knapsacks
w1, w2 = 10, 3
# Function to be called
print(maxWeight(arr, n, w1, w2, 0))
# This code is contributed by Rituraj Jain
C#
// C# implementation of the above approach
using System;
class GFG
{
static int maxN = 31;
static int maxW = 31;
// 3D array to store
// states of DP
static int [ , , ] dp = new int[maxN, maxW, maxW];
// w1_r represents remaining capacity of 1st knapsack
// w2_r represents remaining capacity of 2nd knapsack
// i represents index of the array arr we are working on
static int maxWeight(int [] arr, int n, int w1_r,
int w2_r, int i)
{
// Base case
if (i == n)
return 0;
if (dp[i ,w1_r, w2_r] != -1)
return dp[i, w1_r, w2_r];
// Variables to store the result of three
// parts of recurrence relation
int fill_w1 = 0, fill_w2 = 0, fill_none = 0;
if (w1_r >= arr[i])
fill_w1 = arr[i] +
maxWeight(arr, n, w1_r - arr[i], w2_r, i + 1);
if (w2_r >= arr[i])
fill_w2 = arr[i] +
maxWeight(arr, n, w1_r, w2_r - arr[i], i + 1);
fill_none = maxWeight(arr, n, w1_r, w2_r, i + 1);
// Store the state in the 3D array
dp[i, w1_r, w2_r] = Math.Max(fill_none, Math.Max(fill_w1, fill_w2));
return dp[i, w1_r, w2_r];
}
// Driver code
public static void Main ()
{
// Input array
int [] arr = { 8, 2, 3 };
// Initializing the array with -1
for (int i = 0; i < maxN ; i++)
for (int j = 0; j < maxW ; j++)
for (int k = 0; k < maxW ; k++)
dp[i, j, k] = -1;
// Number of elements in the array
int n = arr.Length;
// Capacity of knapsacks
int w1 = 10, w2 = 3;
// Function to be called
Console.WriteLine(maxWeight(arr, n, w1, w2, 0));
}
}
// This code is contributed by ihritik
输出:
13
时间复杂度: O(N * W1 * W2)。