Minimize cost to buy N elements using given cost Array
Last Updated :
14 Nov, 2022
Given 2 arrays num[] and cost[] containing the number of elements and the cost to buy that many elements respectively. {i.e. cost[i] is the cost to buy num[i] elements}. The task is to minimize the cost to buy exactly N elements.
Examples:
Input: num[] = [1, 2, 10, 50], cost[] = [400, 750, 3250, 15000], N = 7
Output: 2650
Explanation: The minimum amount needed to buy 7 pizzas is 2650.
You can order 3 units of 2 pizzas and 1 unit of 1 pizza.
Input: num[] = [1, 2, 10, 50], cost[] = [400, 750, 3250, 15000], N = 15
Output: 5150
Explanation: The minimum amount needed to buy 15 pizzas is 5150.
You can order 1 unit of 10 pizzas, 2 units of 2 pizzas and 1 unit of 1 pizza.
Approach: The problem can be solved using recursion based on the following idea:
For each element of the num, we are having two choices whether to include that particular combo or not.
- Case 1: When the elements present at num[i] gets include in final result, the cost to these will get add up in our total cost and the total elements will get reduced by the number of pizzas brought.
- Case 2: When the element in num present at num[i] does not get included in final result, no cost will get add up in our total cost.
You can include elements if and only if the elements at num[i] is less than or equal to the total available.
Follow the steps mentioned below to implement the idea:
- Create a recursive function.
- For each call, there are two choices for the element as mentioned above.
- Calculate the value of all possible cases as mentioned above.
- The minimum among them is the required answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int min_cost( int i, int num[], int cost[], int n)
{
if (n == 0)
return cost[i];
if (i == 0) {
if (num[0] <= n)
return cost[0] * n;
else
return 1e9;
}
int not_take = min_cost(i - 1, num, cost, n);
int take = INT_MAX;
if (num[i] <= n) {
take = cost[i] + min_cost(i, num, cost, n - num[i]);
}
return min(take, not_take);
}
int main()
{
int N = 7;
int num[4] = { 1, 2, 10, 50 };
int cost[4] = { 400, 750, 3250, 15000 };
cout << min_cost(3, num, cost, N);
return 0;
}
|
Java
import java.io.*;
import java.util.Scanner;
class GFG {
static int min_cost( int i, int []num, int []cost, int n)
{
if (n == 0 )
return cost[i];
if (i == 0 ) {
if (num[ 0 ] <= n)
return cost[ 0 ] * n;
else
return ( int )1e9;
}
int not_take = min_cost(i - 1 , num, cost, n);
int take = Integer.MAX_VALUE;
if (num[i] <= n) {
take = cost[i] + min_cost(i, num, cost, n - num[i]);
}
return Math.min(take, not_take);
}
public static void main(String[] args) {
int N = 7 ;
int [] num = new int []{ 1 , 2 , 10 , 50 };
int [] cost = new int []{ 400 , 750 , 3250 , 15000 };
System.out.println(min_cost( 3 , num, cost, N));
}
}
|
Python3
def min_cost(i, num, cost, n):
if n is 0 :
return cost[i]
if i is 0 :
if num[ 0 ] < = n:
return cost[ 0 ] * n
else :
return int ( 1e9 )
not_take = min_cost(i - 1 , num, cost, n)
take = float ( "inf" )
if num[i] < = n:
take = cost[i] + min_cost(i, num, cost, n - num[i])
return min (take, not_take)
N = 7
num = [ 1 , 2 , 10 , 50 ]
cost = [ 400 , 750 , 3250 , 15000 ]
print (min_cost( 3 , num, cost, N))
|
C#
using System;
public class GFG {
static int min_cost( int i, int [] num, int [] cost, int n)
{
if (n == 0)
return cost[i];
if (i == 0) {
if (num[0] <= n)
return cost[0] * n;
else
return ( int )1e9;
}
int not_take = min_cost(i - 1, num, cost, n);
int take = Int32.MaxValue;
if (num[i] <= n) {
take = cost[i]
+ min_cost(i, num, cost, n - num[i]);
}
return Math.Min(take, not_take);
}
static public void Main()
{
int N = 7;
int [] num = { 1, 2, 10, 50 };
int [] cost = { 400, 750, 3250, 15000 };
Console.WriteLine(min_cost(3, num, cost, N));
}
}
|
Javascript
<script>
function min_cost(i, num, cost, n) {
if (n == 0)
return cost[i];
if (i == 0) {
if (num[0] <= n)
return cost[0] * n;
else
return 1e9;
}
let not_take = min_cost(i - 1, num, cost, n);
let take = Number.MAX_VALUE;
if (num[i] <= n) {
take = cost[i] + min_cost(i, num, cost, n - num[i]);
}
return Math.min(take, not_take);
}
let N = 7;
let num = [1, 2, 10, 50];
let cost = [400, 750, 3250, 15000];
document.write(min_cost(3, num, cost, N));
</script>
|
Time Complexity: O(2N)
Auxiliary Space: O(N)
Efficient Approach (Using Memoization):
We can use Dynamic Programming to store the answer for overlapping subproblems. We can store the result for the current index and the remaining number of elements in the DP matrix.
The states of DP can be represented as follows:
DP[current index][remaining elements]
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int min_cost( int i, int num[], int cost[], int n,
vector<vector< int > >& dp)
{
if (n == 0)
return 0;
if (i == 0) {
if (num[0] <= n)
return cost[0] * n;
else
return 1e9;
}
if (dp[i][n] != -1)
return dp[i][n];
int not_take = min_cost(i - 1, num, cost, n, dp);
int take = INT_MAX;
if (num[i] <= n) {
take = cost[i]
+ min_cost(i, num, cost, n - num[i], dp);
}
return dp[i][n] = min(take, not_take);
}
int main()
{
int N = 15;
int len = 4;
int num[len] = { 1, 2, 10, 50 };
int cost[len] = { 400, 750, 3250, 15000 };
vector<vector< int > > dp(len, vector< int >(N + 1, -1));
cout << min_cost(len - 1, num, cost, N, dp);
return 0;
}
|
Java
import java.io.*;
import java.util.Scanner;
class GFG {
static int min_cost( int i, int []num, int []cost, int n, int [][] dp) {
if (n == 0 )
return 0 ;
if (i == 0 ) {
if (num[ 0 ] <= n)
return cost[ 0 ] * n;
else
return ( int )1e9;
}
if (dp[i][n] != - 1 )
return dp[i][n];
int not_take = min_cost(i - 1 , num, cost, n, dp);
int take = Integer.MAX_VALUE;
if (num[i] <= n) {
take = cost[i] + min_cost(i, num, cost, n - num[i], dp);
}
return dp[i][n] = Math.min(take, not_take);
}
public static void main(String[] args) {
int N = 15 ;
int len = 4 ;
int [] num = new int [] { 1 , 2 , 10 , 50 };
int [] cost = new int [] { 400 , 750 , 3250 , 15000 };
int [][] dp = new int [len][N + 1 ];
for ( int i = 0 ; i < len; i++) {
for ( int j = 0 ; j <= N; j++) {
dp[i][j] = - 1 ;
}
}
System.out.println(min_cost( 3 , num, cost, N, dp));
}
}
|
Python3
def min_cost(i, num, cost, n, dp):
if (n = = 0 ):
return 0
if (i = = 0 ):
if (num[ 0 ] < = n):
return cost[ 0 ] * n
else :
return 10 * * 9
if (dp[i][n] ! = - 1 ):
return dp[i][n]
notTake = min_cost(i - 1 , num, cost, n, dp)
take = 10 * * 10
if (num[i] < = n):
take = cost[i] + min_cost(i, num, cost, n - num[i], dp)
dp[i][n] = min (take,notTake)
return dp[i][n]
if __name__ = = "__main__" :
N = 15
length = 4
num = [ 1 , 2 , 10 , 50 ]
cost = [ 400 , 750 , 3250 , 15000 ]
dp = []
lis = []
for j in range (N + 1 ):
lis.append( - 1 )
for i in range (length):
dp.append(lis)
print (min_cost(length - 1 ,num,cost,N,dp))
|
C#
using System;
class GFG {
static int min_cost( int i, int [] num, int [] cost, int n,
int [, ] dp)
{
if (n == 0)
return 0;
if (i == 0) {
if (num[0] <= n)
return cost[0] * n;
else
return ( int )1e9;
}
if (dp[i, n] != -1)
return dp[i, n];
int not_take = min_cost(i - 1, num, cost, n, dp);
int take = Int32.MaxValue;
if (num[i] <= n) {
take = cost[i]
+ min_cost(i, num, cost, n - num[i], dp);
}
return dp[i, n] = Math.Min(take, not_take);
}
public static void Main( string [] args)
{
int N = 15;
int len = 4;
int [] num = { 1, 2, 10, 50 };
int [] cost = { 400, 750, 3250, 15000 };
int [, ] dp = new int [len, N + 1];
for ( int i = 0; i < len; i++)
for ( int j = 0; j <= N; j++)
dp[i, j] = -1;
Console.Write(min_cost(len - 1, num, cost, N, dp));
}
}
|
Javascript
function min_cost(i,num,cost,n, dp)
{
if (n == 0)
return 0;
if (i == 0) {
if (num[0] <= n)
return cost[0] * n;
else
return 1e9;
}
if (dp[i][n] != -1)
return dp[i][n];
let not_take = min_cost(i - 1, num, cost, n, dp);
let take = Number.MAX_VALUE;
if (num[i] <= n) {
take = cost[i]
+ min_cost(i, num, cost, n - num[i], dp);
}
return dp[i][n] = Math.min(take, not_take);
}
let N = 15;
let len = 4;
let num = [ 1, 2, 10, 50 ];
let cost = [ 400, 750, 3250, 15000 ];
let dp=[];
let abc = [];
for (let i=0;i<N+1;i++)
{
abc.push(-1);
}
for (let i=0;i<len;i++)
{
dp.push(abc);
}
console.log(min_cost(len - 1, num, cost, N, dp));
|
Time Complexity: O(len*N), where len is the length of the array
Auxiliary Space: O(len*N)
Efficient Approach (Using Tabulation):
As we know that the memoization solution can be further optimized by using the tabulation method and we can reduce the auxiliary stack space taken by the memoization solution.
The states of DP remain the same as follows:
DP[current index][remaining elements]
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N = 15;
int len = 4;
int num[len] = { 1, 2, 10, 50 };
int cost[len] = { 400, 750, 3250, 15000 };
vector<vector< int > > dp(len, vector< int >(N + 1, 1e9));
for ( int i = 0; i <= N; i++) {
dp[0][i] = cost[0] * i;
}
for ( int idx = 1; idx < len; idx++) {
for ( int j = 0; j <= N; j++) {
int not_take = dp[idx - 1][j];
int take = INT_MAX;
if (num[idx] <= j) {
take = cost[idx] + dp[idx][j - num[idx]];
}
dp[idx][j] = min(take, not_take);
}
}
cout << dp[len - 1][N] << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static void main(String[] args) {
int N = 15 ;
int len = 4 ;
int num[] = { 1 , 2 , 10 , 50 };
int cost[] = { 400 , 750 , 3250 , 15000 };
int [][] dp = new int [len][N + 1 ];
for ( int i = 0 ; i < len; i++) {
for ( int j = 0 ; j <= N; j++) {
dp[i][j] = Integer.MAX_VALUE;
}
}
for ( int i = 0 ; i <= N; i++) {
dp[ 0 ][i] = cost[ 0 ] * i;
}
for ( int idx = 1 ; idx < len; idx++) {
for ( int j = 0 ; j <= N; j++) {
int not_take = dp[idx - 1 ][j];
int take = Integer.MAX_VALUE;
if (num[idx] <= j) {
take = cost[idx] + dp[idx][j - num[idx]];
}
dp[idx][j] = min(take, not_take);
}
}
System.out.println(dp[len - 1 ][N]);
}
public static int min( int a, int b) {
if (a < b) return a;
return b;
}
}
|
Python3
N = 15
len = 4
put = 10 ^ 9
maxi = 9223372036854775807
num = [ 1 , 2 , 10 , 50 ]
cost = [ 400 , 750 , 3250 , 15000 ]
dp = [[put] * (N + 1 ) for i in range ( len )]
for i in range ( 0 , N + 1 ):
dp[ 0 ][i] = cost[ 0 ] * i
for idx in range ( 1 , len ):
for j in range ( 0 , N + 1 ):
not_take = dp[idx - 1 ][j]
take = maxi
if (num[idx] < = j):
take = cost[idx] + dp[idx][j - num[idx]]
dp[idx][j] = min (take, not_take)
print (dp[ len - 1 ][N])
|
C#
using System;
public class GFG {
static public void Main()
{
int N = 15;
int len = 4;
int [] num = { 1, 2, 10, 50 };
int [] cost = { 400, 750, 3250, 15000 };
int [, ] dp = new int [len, N + 1];
for ( int i = 0; i < len; i++) {
for ( int j = 0; j <= N; j++) {
dp[i, j] = Int32.MaxValue;
}
}
for ( int i = 0; i <= N; i++) {
dp[0, i] = cost[0] * i;
}
for ( int idx = 1; idx < len; idx++) {
for ( int j = 0; j <= N; j++) {
int not_take = dp[idx - 1, j];
int take = Int32.MaxValue;
if (num[idx] <= j) {
take
= cost[idx] + dp[idx, j - num[idx]];
}
dp[idx, j] = min(take, not_take);
}
}
Console.WriteLine(dp[len - 1, N]);
}
public static int min( int a, int b)
{
if (a < b)
return a;
return b;
}
}
|
Javascript
function min(a, b) {
if (a < b) return a;
return b;
}
function makeArray(d1, d2) {
var arr = new Array(d1), i, l;
for (i = 0, l = d2; i < l; i++) {
arr[i] = new Array(d1);
}
return arr;
}
let N = 15;
let len = 4;
let num = [ 1, 2, 10, 50 ];
let cost= [ 400, 750, 3250, 15000 ];
let dp = makeArray(len,N+1);
for (let i = 0; i < len; i++) {
for (let j = 0; j <= N; j++) {
dp[i][j] = Number.MAX_SAFE_INTEGER;
}
}
for (let i = 0; i <= N; i++) {
dp[0][i] = cost[0] * i;
}
for (let idx = 1; idx < len; idx++) {
for (let j = 0; j <= N; j++) {
let not_take = dp[idx - 1][j];
let take = Number.MAX_SAFE_INTEGER;
if (num[idx] <= j) {
take = cost[idx] + dp[idx][j - num[idx]];
}
dp[idx][j] = Math.min(take, not_take);
}
}
console.log((dp[len - 1][N]));
|
Time Complexity: O(len*N), where len is the length of the array
Auxiliary Space: O(len*N)
Share your thoughts in the comments
Please Login to comment...