Given weights and values of n items and a value k. We need to choose a subset of these items in such a way that ratio of the sum of weight and sum of values of chosen items is K and sum of weight is maximum among all possible subset choices.
 
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
We can solve this problem using dynamic programming. We can make a 2 state dp where dp(i, j) will store maximum possible sum of weights under given conditions when total items are N and required ratio is K. 
Now in two states of dp, we will store the last item chosen and the difference between sum of weight and sum of values. We will multiply item values by K so that second state of dp will actually store (sum of weight – K*(sum of values)) for chosen items. Now we can see that our answer will be stored in dp(N-1, 0) because as last item is (N-1)th so all items are being considered and difference between sum of weight and K*(sum of values) is 0 that means sum of weight and sum of values has a ratio K. 
After defining above dp state we can write transition among states simply as shown below, 
 
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.
In below code a top-down approach is used for solving this dynamic programming and for storing dp states a map is used because the difference can be negative also and the 2D array can create problem in that case and special care need to be taken.
 
C++
| // C++ program to choose item with maximum// sum of weight under given constraint#include <bits/stdc++.h>usingnamespacestd;// memoized recursive method to return maximum// weight with K as ratio of weight and valuesintmaxWeightRec(intwt[], intval[], intK,                  map<pair<int, int>, int>& mp,                            intlast, intdiff){    //  base cases : if no item is remaining    if(last == -1)    {        if(diff == 0)            return0;        else            returnINT_MIN;    }    // first make pair with last chosen item and    // difference between weight and values    pair<int, int> tmp = make_pair(last, diff);    if(mp.find(tmp) != mp.end())        returnmp[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));    returnmp[tmp];}// method returns maximum sum of weight with K// as ration of sum of weight and their valuesintmaxWeight(intwt[], intval[], intK, intN){    map<pair<int, int>, int> mp;    returnmaxWeightRec(wt, val, K, mp, N - 1, 0);}//  Driver code to test above methodsintmain(){    intwt[] = {4, 8, 9};    intval[] = {2, 4, 6};    intN = sizeof(wt) / sizeof(int);    intK = 2;    cout << maxWeight(wt, val, K, N);    return0;} | 
Java
| // Java program to choose item with maximum// sum of weight under given constraintimportjava.awt.Point;importjava.util.HashMap;classTest{    // memoized recursive method to return maximum    // weight with K as ratio of weight and values    staticintmaxWeightRec(intwt[], intval[], intK,                      HashMap<Point, Integer> hm,                                intlast, intdiff)    {        //  base cases : if no item is remaining        if(last == -1)        {            if(diff == 0)                return0;            else                returnInteger.MIN_VALUE;        }             // first make pair with last chosen item and        // difference between weight and values        Point tmp = newPoint(last, diff);        if(hm.containsKey(tmp))            returnhm.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)));             returnhm.get(tmp);    }         // method returns maximum sum of weight with K    // as ration of sum of weight and their values    staticintmaxWeight(intwt[], intval[], intK, intN)    {        HashMap<Point, Integer> hm = newHashMap<>();        returnmaxWeightRec(wt, val, K, hm, N - 1, 0);    }        // Driver method    publicstaticvoidmain(String args[])    {        intwt[] = {4, 8, 9};        intval[] = {2, 4, 6};                intK = 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 constraintINT_MIN =-9999999999defmaxWeightRec(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    iflast ==-1:        ifdiff ==0:            return0        else:            returnINT_MIN    # first make pair with last chosen item and    # difference between weight and values    tmp =(last, diff)    iftmp inmp:        returnmp[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))    returnmp[tmp]defmaxWeight(wt, val, K, N):        # method returns maximum sum of weight with K    # as ration of sum of weight and their values    returnmaxWeightRec(wt, val, K, {}, N -1, 0)# Driver codeif__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 | 
C#
| // C# code for the above approachusingSystem;usingSystem.Collections.Generic;classGFG{    // memoized recursive method to return maximum  // weight with K as ratio of weight and values  staticintmaxWeightRec(int[] wt, int[] val, intK,                          Dictionary<Tuple<int, int>, int> hm,                          intlast, intdiff)  {        //  base cases : if no item is remaining    if(last == -1)    {      if(diff == 0)        return0;      else        returnint.MinValue;    }    // first make pair with last chosen item and    // difference between weight and values    Tuple<int, int> tmp = newTuple<int, int>(last, diff);    if(hm.ContainsKey(tmp))      returnhm[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[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));    returnhm[tmp];  }  // method returns maximum sum of weight with K  // as ration of sum of weight and their values  staticintmaxWeight(int[] wt, int[] val, intK, intN)  {    Dictionary<Tuple<int, int>, int> hm = newDictionary<Tuple<int, int>, int>();    returnmaxWeightRec(wt, val, K, hm, N - 1, 0);  }  // Driver method  publicstaticvoidMain(string[] args)  {    int[] wt = {4, 8, 9};    int[] val = {2, 4, 6};    intK = 2;    Console.WriteLine(maxWeight(wt, val, K, wt.Length));  }}// This code is contributed by lokeshpotta20. | 
Javascript
| <script>// JavaScript program to choose item with maximum// sum of weight under given constraintconst INT_MIN = -9999999999functionmaxWeightRec(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)            return0        else            returnINT_MIN    }    // first make pair with last chosen item and    // difference between weight and values    let tmp = [last, diff]    if(mp.has(tmp))        returnmp.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    mp.set(tmp, Math.max(maxWeightRec(wt, val, K, mp,                            last - 1, diff), wt[last] +                maxWeightRec(wt, val, K, mp,                            last - 1, diff +                            wt[last] - val[last] * K)))    returnmp.get(tmp)}functionmaxWeight(wt, val, K, N){        // method returns maximum sum of weight with K    // as ration of sum of weight and their values    returnmaxWeightRec(wt, val, K, newMap(), N - 1, 0)}// Driver codelet wt = [4, 8, 9]let val = [2, 4, 6]let N = wt.lengthlet K = 2document.write(maxWeight(wt, val, K, N),"</br>")// This code is contributed by shinjanpatra</script> | 
Output: 
 
12
The time complexity of the above code is O(N2), where N is the size of the array. This is because the map stores the results of the subproblems, which is done using a recursive approach.
The space complexity is also O(N2) as the map is used to store the intermediate results.
This article is contributed by Utkarsh Trivedi. If you like neveropen and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the neveropen main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
 
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

 
                                    







