给定 n 个项目的权重和值以及一个值 k。我们需要以这样的方式选择这些项目的一个子集,使得所选项目的权重总和与值总和的比率为 K,并且权重总和在所有可能的子集选择中最大。
Input : weight[] = [4, 8, 9]
values[] = [2, 4, 6]
K = 2
Output : 12
We can choose only first and second item only,
because (4 + 8) / (2 + 4) = 2 which is equal to K
we can't include third item with weight 9 because
then ratio condition won't be satisfied so result
will be (4 + 8) = 12
我们可以使用动态规划来解决这个问题。我们可以创建一个 2 状态 dp,其中 dp(i, j) 将在给定条件下存储最大可能的权重总和,当总项目数为 N 且所需比率为 K 时。
现在在 dp 的两种状态下,我们将存储最后选择的项目以及权重总和和值总和之间的差值。我们将项目值乘以 K,这样 dp 的第二个状态将实际存储所选项目的(权重总和 – K*(值总和))。现在我们可以看到我们的答案将存储在 dp(N-1, 0) 中,因为最后一项是第 (N-1) 项,因此正在考虑所有项目以及权重总和与 K*(值总和)之间的差异是 0,这意味着权重之和和值之和的比率为 K。
在定义上面的 dp 状态后,我们可以简单地编写状态之间的转换,如下所示,
dp(last, diff) = max (dp(last - 1, diff),
dp(last-1, diff + wt[last] - val[last]*K))
dp(last – 1, diff) represents the condition when current
item is not chosen and
dp(last – 1, diff + wt[last] – val[last] * K)) represents
the condition when current item is chosen so difference
is updated with weight and value of current item.
在下面的代码中,自上而下的方法用于解决此动态规划并使用映射存储 dp 状态,因为差异也可能为负,并且在这种情况下二维数组可能会产生问题,需要特别注意。
C++
// C++ program to choose item with maximum
// sum of weight under given constraint
#include
using namespace std;
// memoized recursive method to return maximum
// weight with K as ratio of weight and values
int maxWeightRec(int wt[], int val[], int K,
map, int>& mp,
int last, int diff)
{
// base cases : if no item is remaining
if (last == -1)
{
if (diff == 0)
return 0;
else
return INT_MIN;
}
// first make pair with last chosen item and
// difference between weight and values
pair tmp = make_pair(last, diff);
if (mp.find(tmp) != mp.end())
return mp[tmp];
/* choose maximum value from following two
1) not selecting the current item and calling
recursively
2) selection current item, including the weight
and updating the difference before calling
recursively */
mp[tmp] = max(maxWeightRec(wt, val, K, mp, last - 1, diff),
wt[last] + maxWeightRec(wt, val, K, mp,
last - 1, diff + wt[last] - val[last] * K));
return mp[tmp];
}
// method returns maximum sum of weight with K
// as ration of sum of weight and their values
int maxWeight(int wt[], int val[], int K, int N)
{
map, int> mp;
return maxWeightRec(wt, val, K, mp, N - 1, 0);
}
// Driver code to test above methods
int main()
{
int wt[] = {4, 8, 9};
int val[] = {2, 4, 6};
int N = sizeof(wt) / sizeof(int);
int K = 2;
cout << maxWeight(wt, val, K, N);
return 0;
}
Java
// Java program to choose item with maximum
// sum of weight under given constraint
import java.awt.Point;
import java.util.HashMap;
class Test
{
// memoized recursive method to return maximum
// weight with K as ratio of weight and values
static int maxWeightRec(int wt[], int val[], int K,
HashMap hm,
int last, int diff)
{
// base cases : if no item is remaining
if (last == -1)
{
if (diff == 0)
return 0;
else
return Integer.MIN_VALUE;
}
// first make pair with last chosen item and
// difference between weight and values
Point tmp = new Point(last, diff);
if (hm.containsKey(tmp))
return hm.get(tmp);
/* choose maximum value from following two
1) not selecting the current item and calling
recursively
2) selection current item, including the weight
and updating the difference before calling
recursively */
hm.put(tmp,Math.max(maxWeightRec(wt, val, K, hm, last - 1, diff),
wt[last] + maxWeightRec(wt, val, K, hm,
last - 1, diff + wt[last] - val[last] * K)));
return hm.get(tmp);
}
// method returns maximum sum of weight with K
// as ration of sum of weight and their values
static int maxWeight(int wt[], int val[], int K, int N)
{
HashMap hm = new HashMap<>();
return maxWeightRec(wt, val, K, hm, N - 1, 0);
}
// Driver method
public static void main(String args[])
{
int wt[] = {4, 8, 9};
int val[] = {2, 4, 6};
int K = 2;
System.out.println(maxWeight(wt, val, K, wt.length));
}
}
// This code is contributed by Gaurav Miglani
Python3
# Python3 program to choose item with maximum
# sum of weight under given constraint
INT_MIN = -9999999999
def maxWeightRec(wt, val, K, mp, last, diff):
# memoized recursive method to return maximum
# weight with K as ratio of weight and values
# base cases : if no item is remaining
if last == -1:
if diff == 0:
return 0
else:
return INT_MIN
# first make pair with last chosen item and
# difference between weight and values
tmp = (last, diff)
if tmp in mp:
return mp[tmp]
# choose maximum value from following two
# 1) not selecting the current item and
# calling recursively
# 2) selection current item, including
# the weight and updating the difference
# before calling recursively
mp[tmp] = max(maxWeightRec(wt, val, K, mp,
last - 1, diff), wt[last] +
maxWeightRec(wt, val, K, mp,
last - 1, diff +
wt[last] - val[last] * K))
return mp[tmp]
def maxWeight(wt, val, K, N):
# method returns maximum sum of weight with K
# as ration of sum of weight and their values
return maxWeightRec(wt, val, K, {}, N - 1, 0)
# Driver code
if __name__ == "__main__":
wt = [4, 8, 9]
val = [2, 4, 6]
N = len(wt)
K = 2
print(maxWeight(wt, val, K, N))
# This code is contributed
# by vibhu4agarwal
输出:
12
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。