📜  选择给定重量和价值比的最大重量

📅  最后修改于: 2021-09-17 06:57:32             🧑  作者: Mango

给定 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 现场工作专业课程学生竞争性编程现场课程