Open In App

Minimum Cost with Bonus Items in Shopping

Given array p where p[i] is the price of ith item. The shop also offers bonuses on all items. If he buys the ith item he can get any f[i] items free of cost, the task is to return the minimum amount of money needed to buy n items.

Note: We won’t get [i] free items if the ith item has been received free of cost and not bought.



Examples:

Input: n = 4, p = {10, 20, 5, 3}, f = {2, 0, 1, 1}
Output: 8
Explanation: Will buy 3rd and 4th items and The week will get 1st and 2nd items free of cost because of the bonus that he got after buying 3rd and 4th items. So the answer is 8.



Input: n = 3, p = {1, 10, 100}, f = {0, 0, 0}
Output: 111
Explanation: can’t get any free items. So he will have to pay for all the three items. So the answer is 111.

Approach: This can be solved with the following idea:

The problem can be solved using dynamic programming. The main idea is to consider each item and make a decision on whether to buy it or skip it while keeping track of the total cost. To minimize the cost, we should consider the bonuses provided for each item.

Below are the steps involved:

Below is the implementation of the code:




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Intializing a Dp
long long dp[500][1001];
 
long long memo(int i, int t, vector<int>& price,
               vector<int>& time, int n)
{
 
    // If array end is reached
    if (i >= n) {
        if (t >= 0)
            return 0;
        return 1e18;
    }
 
    if (n - i <= t)
        return 0;
 
    // If values has already found
    if (dp[i][t + 500] != -1)
        return dp[i][t + 500];
 
    // Get the value
    return dp[i][t + 500]
           = min(memo(i + 1, t + time[i], price, time, n)
                     + price[i],
                 memo(i + 1, t - 1, price, time, n));
}
 
// Function to calculate minimum money
long long minCost(int n, vector<int>& p, vector<int>& f)
{
 
    // Filling all values with 1
    memset(dp, -1, sizeof(dp));
 
    // Function to fill dp
    return memo(0, 0, p, f, n);
}
 
// Driver code
int main()
{
    int n = 4;
    vector<int> p = { 10, 20, 5, 3 };
    vector<int> f = { 2, 0, 1, 1 };
 
    // Function call
    cout << minCost(n, p, f);
    return 0;
}




import java.util.Arrays;
import java.util.Vector;
 
public class MinimumMoney {
 
    // Initializing a Dp
    static long[][] dp = new long[500][1001];
 
    static long memo(int i, int t, Vector<Integer> price, Vector<Integer> time, int n) {
 
        // If array end is reached
        if (i >= n) {
            if (t >= 0)
                return 0;
            return (long) 1e18;
        }
 
        if (n - i <= t)
            return 0;
 
        // If values have already been found
        if (dp[i][t + 500] != -1)
            return dp[i][t + 500];
 
        // Get the value
        return dp[i][t + 500] = Math.min(memo(i + 1, t + time.get(i), price, time, n) + price.get(i),
                memo(i + 1, t - 1, price, time, n));
    }
 
    // Function to calculate minimum money
    static long minCost(int n, Vector<Integer> p, Vector<Integer> f) {
 
        // Filling all values with -1
        for (long[] row : dp) {
            Arrays.fill(row, -1);
        }
 
        // Function to fill dp
        return memo(0, 0, p, f, n);
    }
 
    // Driver code
    public static void main(String[] args) {
        int n = 4;
        Vector<Integer> p = new Vector<>(Arrays.asList(10, 20, 5, 3));
        Vector<Integer> f = new Vector<>(Arrays.asList(2, 0, 1, 1));
 
        // Function call
        System.out.println(minCost(n, p, f));
    }
}
 
// This code is contributed by shivamgupta0987654321




# Initializing a DP
dp = [[-1] * 1001 for _ in range(500)]
 
def memo(i, t, price, time, n):
    # If array end is reached
    if i >= n:
        if t >= 0:
            return 0
        return float('inf')
 
    if n - i <= t:
        return 0
 
    # If values have already been found
    if dp[i][t + 500] != -1:
        return dp[i][t + 500]
 
    # Get the value
    dp[i][t + 500] = min(memo(i + 1, t + time[i], price, time, n) + price[i],
                         memo(i + 1, t - 1, price, time, n))
 
    return dp[i][t + 500]
 
# Function to calculate minimum money
def min_cost(n, p, f):
    # Filling all values with 1
    for i in range(500):
        dp[i] = [-1] * 1001
 
    # Function to fill dp
    return memo(0, 0, p, f, n)
 
# Driver code
if __name__ == "__main__":
    n = 4
    p = [10, 20, 5, 3]
    f = [2, 0, 1, 1]
 
    # Function call
    print(min_cost(n, p, f))




using System;
using System.Collections.Generic;
 
public class MinimumMoney
{
    // Initializing a Dp
    static long[,] dp = new long[500, 1001];
 
    static long Memo(int i, int t, List<int> price, List<int> time, int n)
    {
        // If array end is reached
        if (i >= n)
        {
            if (t >= 0)
                return 0;
            return (long)1e18;
        }
 
        if (n - i <= t)
            return 0;
 
        // If values have already been found
        if (dp[i, t + 500] != -1)
            return dp[i, t + 500];
 
        // Get the value
        return dp[i, t + 500] = Math.Min(Memo(i + 1, t + time[i], price, time, n) + price[i],
                                        Memo(i + 1, t - 1, price, time, n));
    }
 
    // Function to calculate minimum money
    static long MinCost(int n, List<int> p, List<int> f)
    {
        // Filling all values with -1
        for (int i = 0; i < 500; i++)
        {
            for (int j = 0; j < 1001; j++)
            {
                dp[i, j] = -1;
            }
        }
 
        // Function to fill dp
        return Memo(0, 0, p, f, n);
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int n = 4;
        List<int> p = new List<int> { 10, 20, 5, 3 };
        List<int> f = new List<int> { 2, 0, 1, 1 };
 
        // Function call
        Console.WriteLine(MinCost(n, p, f)); // Output should be 8
    }
}




// Initializing a DP
const dp = new Array(500).fill(null).map(() => new Array(1001).fill(-1));
 
function memo(i, t, price, time, n) {
  // If array end is reached
  if (i >= n) {
    if (t >= 0) {
      return 0;
    }
    return Infinity;
  }
 
  if (n - i <= t) {
    return 0;
  }
 
  // If values have already been found
  if (dp[i][t + 500] !== -1) {
    return dp[i][t + 500];
  }
 
  // Get the value
  dp[i][t + 500] = Math.min(
    memo(i + 1, t + time[i], price, time, n) + price[i],
    memo(i + 1, t - 1, price, time, n)
  );
 
  return dp[i][t + 500];
}
 
// Function to calculate minimum money
function minCost(n, p, f) {
  // Filling all values with 1
  for (let i = 0; i < 500; i++) {
    dp[i] = new Array(1001).fill(-1);
  }
 
  // Function to fill dp
  return memo(0, 0, p, f, n);
}
 
// Driver code
const n = 4;
const p = [10, 20, 5, 3];
const f = [2, 0, 1, 1];
 
// Function call
console.log(minCost(n, p, f));
 
// This code is contributed by shivamgupta0987654321

Output
8






Time Complexity: O(N)
Auxiliary Space: O(500 * 1001)


Article Tags :