Last Updated: 6 Sep, 2022

SICK NINJA

Hard

Problem statement

Ninja is having some health issues. So he decided to buy fruits to get nutrition. There are ‘N’ number of fruits. Each fruit has some amount of nutrition and a specific cost.

Ninja has ‘M’ units of money. You need to find the maximum amount of nutrition Ninja can get and the total cost to get maximum nutrition. The ninja can buy any number of fruits, but he can spend only at most ‘M’ units of money.

Note: If there are multiple values of costs possible for maximum nutrition, you need to find the minimum one.

Example:
Suppose there are 3 fruits with costs 1, 2, 3 and nutrition  2, 2, 3 units respectively. Ninja has 3 units of money. Then, the ninja can take fruits with costs 1 and 2, having the maximum nutritional value of  4 units for a cost of 3 units.
Input Format :
The first line contains ‘T,’ denoting the number of test cases.

The first line of each test case contains two space-separated integers, ‘M’ and ‘N’, denoting the amount of money ninja has and the total number of fruits.

The next ‘N’ line contains two space-separated integers, ‘X’ and ‘Y’, denoting each fruit's cost and nutrition value.
Output Format :
Print two space-separated integers the maximum amount of nutrition Ninja can get and the total cost to get maximum nutrition.
Note :
You don't need to print anything. It has already been taken care of. Just implement the given function.
Constraints :
1  <= N <= 1000
1 < = M <=1000
0 < = X <= 1000
0 < = Y <= 1000

Time Limit: 1 sec

Approaches

01 Approach

We can recursively try out all the possible sets of fruits possible. We can add the nutrition and cost of each fruit we include in the set. We have two options for each fruit either to take it or not. We can recursively try out for both of these options and return the best of them. 


 

When we reach the end of the array, we can simply return the current value of nutrition and cost.


 

The steps are as follows:-
 

// Recursive function to find maximum strength

function  getMaxNutritionUtil(int index, [FRUIT] FRUITS,int N, 

                           int cost, int nutrition, int M ):
 

  1. If index==N
    • If ( cost > M )
      • Return ( nutrition, cost ) = ( 0, 0 ).
    • Return ( nutrition, cost ).
  2. Call getMaxNutritionUtil with ( index + 1, FRUITS, N, cost + FRUITS [ index ].cost, nutrition +  FRUITS [ index ].nutrition, M ) and store it in a variable ‘maxNutrition1’.
  3. Call getMaxNutritionUtil with ( index + 1, FRUITS, N, cost, nutrition, M ) and store it in a variable ‘‘maxNutrition2’.
  4. If ( ‘maxNutrition2.nutrition > ‘maxNutrition1.nutrition ).
    • Return ‘maxNutrition2’.
  5. If ( maxNutrition2.nutrition == maxNutrition1.nutrition and maxNutrition2.cost < ‘maxNutrition1.cost).
    • Return ‘maxNutrition2’.
  6. Return ‘maxNutrition1’.
     

function getMaxNutrition ( [FRUIT] FRUITS, int N, int M):

 

  1. Call getMaxNutritionUtil with index as 0, cost as 0 and nutrition as 0 and store it in a variable ‘maxNutritionr’.
  2. Return ‘maxNutrition’.

02 Approach

We can use the memoization technique to store the result for each state with a particular ‘index’ and ‘cost.’ This way, we can save time from recalculating the already calculated results.

 

For memoization, let us define a 2-dimensional matrix DP of size (N+1) * ( M + 1 ).

 

Where DP[ i ] [ j ] denotes the best possible values of nutrition and cost for index from ‘i’ to ‘N’ - 1 having already spent ‘j’ units of money.
 

The steps are as follows:-

 

      function  getMaxNutritionUtil(int index, [FRUIT] FRUITS,int N,

                      int cost, int M, [ FRUIT ] [ FRUIT ] DP ):

  1. If index==’N’
    • Return ( cost, nutrition as 0 ).
  2. If ( DP [ index ] [ cost ].cost != -1)
    • return DP [ index] [ cost].
  3. Call getMaxNutritionUtil with ( index + 1, FRUITS, N, cost, M ) and store it in a variable ‘maxNutrition1’.
  4. Update dp [ index ] [cost ] with ‘maxNutrition1’.
  5. If ( cost + FRUITS [ index].cost <= M )
    • Call getMaxNutritionUtil with ( index + 1, FRUITS, N, cost + FRUITS [ index ].cost, nutrition , M ) and store it in ‘maxNutrition2’.
    • maxNutrition2.nutrition = maxNutrition2.nutrition +               fruits [ index ].cost
    • If ( maxNutrition2.nutrition > maxNutrition1.nutrition ).
      • DP [ index ] [ cost ] = ‘maxNutrition2’.
    • If ( maxNutrition2.nutrition == maxNutrition1.nutrition and maxNutrition2.cost < maxNutrition )
      • DP [ index] [ cost ] = maxNutrition2’.
  6. Return DP [ index ] [ cost ].

 

function getMaxNutrition ( [ FRUIT] FRUITS, int N, int M):

  1. Initialise a two dimensional matrix of size ( N + 1 ) * ( M +1 ) with cost and nutrition values as -1.
  2. Call getMaxNutritionUtil with index as 0, cost as 0 and DP and store it in a variable ‘maxNutrition’.
  3. Return ‘maxNutrition’.

03 Approach

The idea is the same as memoization. Here, we can use the idea of iterative dynamic programming. Let us define a 2-dimensional matrix DP of size (N+1) * ( M + 1 ).

 

 Where DP[ i ] [ j ] denotes the best possible values of nutrition and cost for index from ‘i’ to ‘N’ - 1 having already spent ‘j’ units of money.

 

 We have two options for each fruit when to take it or not. We can try out both of these options and store the best answer in the ‘DP’ matrix.

 

The steps are as follows:-

 

function getMaxNutrition ([FRUIT] FRUITS , int N ,int M)

  1. Initialise a two-dimensional matrix of FRUIT  ‘DP’ of size (N+1) *(M+1).
  2. Run a loop from i = ‘N’ to 0 :
    • Run a loop from j= 0 to ‘M’ :
      • If ( i  == N )
        • DP [ i ] [ j ]( cost, nutrition ) = (  j, 0 ) .
        • continue.
      • Initialise DP [ i ] [ j ] with DP [ i+1 ] [ j ]
      • If ( j + FRUITS [ i ] . cost <= M )
        • Initialise ‘maxNutrition1’ with DP [ i + 1 ] [ j + FRUITS [ i ].cost
        • maxNutrition1.nutrition =  maxNutrition1.nutrition + FRUITS [ i ].nutrition
        • If ( maxNutrition1.nutrition > DP [ i ] [ j ] . nutrition )
          1. DP [ i ] [ j ] = maxNutrition1.
        • If (  maxNutrition1.nutrition == DP [ i ] [ j ] and  maxNutrition1.cost < DP [ i ] [ j ] )
          1. DP [ i ] [ j ] = maxNutrition1.
  3. return DP [ 0 ] [ 0 ] .