给定一个由物品的重量组成的整数数组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 背包的文章。
朴素的方法:对于每个查询,我们可以生成所有可能的权重子集,并在所有适合背包的子集中选择权重最大的子集。因此,回答每个查询将花费指数时间。
高效的方法:我们将使用动态编程优化回答每个查询。
0-1 背包使用 2-D DP 解决,一种状态“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”值预先计算二维数组 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.MaxValue;
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= { 3, 8, 9 };
int n = w.Length;
// Performing required
// pre-computation
preCompute(w, n);
int[] queries = { 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 sanjoy_62.
Javascript
11
9
3
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。