给定一个由项目权重组成的整数数组W []和一些由背包容量C组成的查询,对于每个查询,我们都可以将最大重量放入背包中。 C的值不超过某个整数C_MAX 。
例子:
Input: W[] = {3, 8, 9} q = {11, 10, 4}
Output:
11
9
3
If C = 11: select 3 + 8 = 11
If C = 10: select 9
If C = 4: select 3
Input: W[] = {1, 5, 10} q = {6, 14}
Output:
6
11
建议您先尝试使用0-1背包阅读本文,然后再尝试解决此问题。
天真的方法:对于每个查询,我们都可以生成所有可能的权重子集,然后在适合背包的所有那些子集中选择权重最大的子集。因此,回答每个查询将花费指数时间。
高效的方法:我们将使用动态编程来优化对每个查询的回答。
使用2-D DP解决0-1背包问题,一种状态为“ i”作为当前索引(即选择或拒绝),另一种状态为剩余容量“ R”。
递归关系为
dp[i][R] = max(arr[i] + dp[i + 1][R – arr[i]], dp[i + 1][R])
我们将为O(C_MAX * i)中1到C_MAX之间的’C’的每个可能值预先计算2-d数组dp [i] [C]。
使用此预计算,我们可以在O(1)时间内回答每个查询。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
#define C_MAX 30
#define max_arr_len 10
using namespace std;
// To store states of DP
int dp[max_arr_len][C_MAX + 1];
// To check if a state has
// been solved
bool v[max_arr_len][C_MAX + 1];
// Function to compute the states
int findMax(int i, int r, int w[], int n)
{
// Base case
if (r < 0)
return INT_MIN;
if (i == n)
return 0;
// Check if a state has
// been solved
if (v[i][r])
return dp[i][r];
// Setting a state as solved
v[i][r] = 1;
dp[i][r] = max(w[i] + findMax(i + 1, r - w[i], w, n),
findMax(i + 1, r, w, n));
// Returning the solved state
return dp[i][r];
}
// Function to pre-compute the states
// dp[0][0], dp[0][1], .., dp[0][C_MAX]
void preCompute(int w[], int n)
{
for (int i = C_MAX; i >= 0; i--)
findMax(0, i, w, n);
}
// Function to answer a query in O(1)
int ansQuery(int w)
{
return dp[0][w];
}
// Driver code
int main()
{
int w[] = { 3, 8, 9 };
int n = sizeof(w) / sizeof(int);
// Performing required
// pre-computation
preCompute(w, n);
int queries[] = { 11, 10, 4 };
int q = sizeof(queries) / sizeof(queries[0]);
// Perform queries
for (int i = 0; i < q; i++)
cout << ansQuery(queries[i]) << endl;
return 0;
}
Java
// Java implementation of the approach
class GFG
{
static int C_MAX = 30;
static int max_arr_len = 10;
// To store states of DP
static int dp [][] = new int [max_arr_len][C_MAX + 1];
// To check if a state has
// been solved
static boolean v[][]= new boolean [max_arr_len][C_MAX + 1];
// Function to compute the states
static int findMax(int i, int r, int w[], int n)
{
// Base case
if (r < 0)
return Integer.MIN_VALUE;
if (i == n)
return 0;
// Check if a state has
// been solved
if (v[i][r])
return dp[i][r];
// Setting a state as solved
v[i][r] = true;
dp[i][r] = Math.max(w[i] + findMax(i + 1, r - w[i], w, n),
findMax(i + 1, r, w, n));
// Returning the solved state
return dp[i][r];
}
// Function to pre-compute the states
// dp[0][0], dp[0][1], .., dp[0][C_MAX]
static void preCompute(int w[], int n)
{
for (int i = C_MAX; i >= 0; i--)
findMax(0, i, w, n);
}
// Function to answer a query in O(1)
static int ansQuery(int w)
{
return dp[0][w];
}
// Driver code
public static void main (String[] args)
{
int w[] = new int []{ 3, 8, 9 };
int n = w.length;
// Performing required
// pre-computation
preCompute(w, n);
int queries[] = new int [] { 11, 10, 4 };
int q = queries.length;
// Perform queries
for (int i = 0; i < q; i++)
System.out.println(ansQuery(queries[i]));
}
}
// This code is contributed by ihritik
Python3
# Python3 implementation of the approach
import numpy as np
import sys
C_MAX = 30
max_arr_len = 10
# To store states of DP
dp = np.zeros((max_arr_len,C_MAX + 1));
# To check if a state has
# been solved
v = np.zeros((max_arr_len,C_MAX + 1));
INT_MIN = -(sys.maxsize) + 1
# Function to compute the states
def findMax(i, r, w, n) :
# Base case
if (r < 0) :
return INT_MIN;
if (i == n) :
return 0;
# Check if a state has
# been solved
if (v[i][r]) :
return dp[i][r];
# Setting a state as solved
v[i][r] = 1;
dp[i][r] = max(w[i] + findMax(i + 1, r - w[i], w, n),
findMax(i + 1, r, w, n));
# Returning the solved state
return dp[i][r];
# Function to pre-compute the states
# dp[0][0], dp[0][1], .., dp[0][C_MAX]
def preCompute(w, n) :
for i in range(C_MAX, -1, -1) :
findMax(0, i, w, n);
# Function to answer a query in O(1)
def ansQuery(w) :
return dp[0][w];
# Driver code
if __name__ == "__main__" :
w = [ 3, 8, 9 ];
n = len(w)
# Performing required
# pre-computation
preCompute(w, n);
queries = [ 11, 10, 4 ];
q = len(queries)
# Perform queries
for i in range(q) :
print(ansQuery(queries[i]));
# This code is coontributed by AnkitRai01
C#
// C# implementation of the approach
using System;
class GFG
{
static int C_MAX = 30;
static int max_arr_len = 10;
// To store states of DP
static int [ , ] dp = new int [max_arr_len, C_MAX + 1];
// To check if a state has
// been solved
static bool [ , ] v = new bool [max_arr_len, C_MAX + 1];
// Function to compute the states
static int findMax(int i, int r, int [] w, int n)
{
// Base case
if (r < 0)
return Int32.MinValue;
if (i == n)
return 0;
// Check if a state has
// been solved
if (v[i, r])
return dp[i, r];
// Setting a state as solved
v[i, r] = true;
dp[i, r] = Math.Max(w[i] + findMax(i + 1, r - w[i], w, n),
findMax(i + 1, r, w, n));
// Returning the solved state
return dp[i, r];
}
// Function to pre-compute the states
// dp[0][0], dp[0][1], .., dp[0][C_MAX]
static void preCompute(int []w, int n)
{
for (int i = C_MAX; i >= 0; i--)
findMax(0, i, w, n);
}
// Function to answer a query in O(1)
static int ansQuery(int w)
{
return dp[0, w];
}
// Driver code
public static void Main ()
{
int []w = new int []{ 3, 8, 9 };
int n = w.Length;
// Performing required
// pre-computation
preCompute(w, n);
int [] queries = new int [] { 11, 10, 4 };
int q = queries.Length;
// Perform queries
for (int i = 0; i < q; i++)
Console.WriteLine (ansQuery(queries[i]));
}
}
// This code is contributed by ihritik
输出:
11
9
3