Minimum cost of purchasing at least X chocolates
Given a positive integer X and an array arr[] consisting of N pairs, where each pair (A, B) represents a box, where A represents the number of chocolates and B represents the cost of the current box. The task is to find the minimum cost to buy at least X number of chocolates.
Examples:
Input: arr[] = {{4, 3}, {3, 2}, {2, 4}, {1, 3}, {4, 2}}, X = 7
Output: 4
Examples: Select the 2nd and the 5th box. Number of chocolates = 3 + 4 = 7.
Total cost = 2 + 2 = 4, which is the minimum cost to buy at least 7 chocolates.
Input: arr[] = {{10, 2}, {5, 3}}, X = 20
Output: -1
Examples: There exists no set of boxes which satisfies the given condition.
Naive Approach: The simplest approach is to use recursion, to consider all subsets of boxes and calculate the cost and number of chocolates of all subsets. From all such subsets, pick the subset having the minimum cost and at least X chocolates.
Optimal Sub-structure: To consider all subsets of items, there can be two cases for every box.
- Case 1: The item is included in the optimal subset. If the current box is included, then add the cost of this box and decrement X by the number of chocolates in the current box. And recur for the remaining X chocolates moving to the next index.
- Case 2: The item is not included in the optimal set. If the current box is not included, then just recur for the remaining X chocolates moving to the next index.
Therefore, the minimum cost that can be obtained is the minimum of the above two cases. Handle the base case if X ≤ 0, return 0.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int findMinCost(pair< int , int > arr[],
int X, int n, int i = 0)
{
if (X <= 0)
return 0;
if (i >= n)
return INT_MAX;
int inc = findMinCost(arr,
X - arr[i].first,
n, i + 1);
if (inc != INT_MAX)
inc += arr[i].second;
int exc = findMinCost(arr, X, n, i + 1);
return min(inc, exc);
}
int main()
{
pair< int , int > arr[] = {
{ 4, 3 }, { 3, 2 },
{ 2, 4 }, { 1, 3 }, { 4, 2 }
};
int X = 7;
int n = sizeof (arr) / sizeof (arr[0]);
int ans = findMinCost(arr, X, n);
if (ans != INT_MAX)
cout << ans;
else
cout << -1;
return 0;
}
|
Java
class GFG{
static int findMinCost( int [][] arr, int X,
int n, int i)
{
if (X <= 0 )
return 0 ;
if (i >= n)
return Integer.MAX_VALUE;
int inc = findMinCost(arr, X - arr[i][ 0 ],
n, i + 1 );
if (inc != Integer.MAX_VALUE)
inc += arr[i][ 1 ];
int exc = findMinCost(arr, X, n, i + 1 );
return Math.min(inc, exc);
}
public static void main(String[] args)
{
int [][] arr = { { 4 , 3 }, { 3 , 2 },
{ 2 , 4 }, { 1 , 3 },
{ 4 , 2 } };
int X = 7 ;
int n = arr.length;
int ans = findMinCost(arr, X, n, 0 );
if (ans != Integer.MAX_VALUE)
System.out.println(ans);
else
System.out.println(- 1 );
}
}
|
Python3
def findMinCost(arr,X, n, i = 0 ):
if (X < = 0 ):
return 0
if (i > = n):
return 10 * * 8
inc = findMinCost(arr,X - arr[i][ 0 ], n, i + 1 )
if (inc ! = 10 * * 8 ):
inc + = arr[i][ 1 ]
exc = findMinCost(arr, X, n, i + 1 )
return min (inc, exc)
if __name__ = = '__main__' :
arr = [[ 4 , 3 ], [ 3 , 2 ],[ 2 , 4 ], [ 1 , 3 ], [ 4 , 2 ]]
X = 7
n = len (arr)
ans = findMinCost(arr, X, n)
if (ans ! = 10 * * 8 ):
print (ans)
else :
print ( - 1 )
|
C#
using System;
class GFG
{
static int findMinCost( int [, ] arr, int X, int n,
int i = 0)
{
if (X <= 0)
return 0;
if (i >= n)
return Int32.MaxValue;
int inc = findMinCost(arr, X - arr[i, 0], n, i + 1);
if (inc != Int32.MaxValue)
inc += arr[i, 1];
int exc = findMinCost(arr, X, n, i + 1);
return Math.Min(inc, exc);
}
public static void Main()
{
int [, ] arr = {
{ 4, 3 }, { 3, 2 }, { 2, 4 }, { 1, 3 }, { 4, 2 }
};
int X = 7;
int n = arr.GetLength(0);
int ans = findMinCost(arr, X, n);
if (ans != Int32.MaxValue)
Console.Write(ans);
else
Console.Write(-1);
}
}
|
Javascript
<script>
function findMinCost( arr, X, n, i = 0)
{
if (X <= 0)
return 0;
if (i >= n)
return Number.MAX_SAFE_INTEGER;
let inc = findMinCost(arr,
X - arr[i][0],
n, i + 1);
if (inc != Number.MAX_SAFE_INTEGER)
inc += arr[i][1];
let exc = findMinCost(arr, X, n, i + 1);
return Math.min(inc, exc);
}
let arr = [
[ 4, 3 ], [ 3, 2 ],
[ 2, 4 ], [ 1, 3 ], [ 4, 2 ]
];
let X = 7;
let n = arr.length;
let ans = findMinCost(arr, X, n);
if (ans != Number.MAX_SAFE_INTEGER)
document.write(ans)
else
document.write(-1)
</script>
|
Time Complexity: O(2N)
Auxiliary Space: O(1)
Another Approach: To optimize the above approach, the idea is to use dynamic programming since the problem contains overlapping subproblems and optimal substructure property. The idea is to use memoization to solve the problem. Create a 2D array, dp[N][X] to store the results in the recursive calls. If a particular state is already computed, then return its result stored in the table in constant time.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int findMinCostUtil(pair< int , int > arr[],
int X, int n,
int ** dp, int i = 0)
{
if (X <= 0)
return 0;
if (i >= n)
return INT_MAX;
if (dp[i][X] != INT_MAX)
return dp[i][X];
int inc = findMinCostUtil(arr,
X - arr[i].first,
n, dp,
i + 1);
if (inc != INT_MAX)
inc += arr[i].second;
int exc = findMinCostUtil(arr, X, n,
dp, i + 1);
dp[i][X] = min(inc, exc);
return dp[i][X];
}
void findMinCost(pair< int , int > arr[], int X, int n)
{
int ** dp = new int *[n + 1];
for ( int i = 0; i <= n; i++) {
dp[i] = new int [X + 1];
for ( int j = 0; j <= X; j++)
dp[i][j] = INT_MAX;
}
int ans = findMinCostUtil(arr, X, n, dp);
if (ans != INT_MAX)
cout << ans;
else
cout << -1;
}
int main()
{
pair< int , int > arr[] = {
{ 4, 3 }, { 3, 2 },
{ 2, 4 }, { 1, 3 }, { 4, 2 }
};
int X = 7;
int n = sizeof (arr) / sizeof (arr[0]);
findMinCost(arr, X, n);
return 0;
}
|
Java
class GFG{
static int findMinCostUtil( int [][] arr, int X, int n,
int [][] dp, int i)
{
if (X <= 0 )
return 0 ;
if (i >= n)
return Integer.MAX_VALUE;
if (dp[i][X] != Integer.MAX_VALUE)
return dp[i][X];
int inc = findMinCostUtil(arr, X - arr[i][ 0 ],
n, dp, i + 1 );
if (inc != Integer.MAX_VALUE)
inc += arr[i][ 1 ];
int exc = findMinCostUtil(arr, X, n,
dp, i + 1 );
dp[i][X] = Math.min(inc, exc);
return dp[i][X];
}
static void findMinCost( int [][] arr, int X, int n)
{
int [][] dp = new int [n + 1 ][X + 1 ];
for ( int i = 0 ; i <= n; i++)
{
for ( int j = 0 ; j <= X; j++)
dp[i][j] = Integer.MAX_VALUE;
}
int ans = findMinCostUtil(arr, X, n, dp, 0 );
if (ans != Integer.MAX_VALUE)
System.out.println(ans);
else
System.out.println(- 1 );
}
public static void main(String[] args)
{
int [][] arr = { { 4 , 3 }, { 3 , 2 },
{ 2 , 4 }, { 1 , 3 },
{ 4 , 2 } };
int X = 7 ;
int n = 5 ;
findMinCost(arr, X, n);
}
}
|
Python3
import sys
def findMinCostUtil(arr, X, n, dp, i):
if (X < = 0 ):
return 0
if (i > = n):
return sys.maxsize
if (dp[i][X] ! = sys.maxsize):
return dp[i][X]
inc = findMinCostUtil(arr, X - arr[i][ 0 ], n, dp, i + 1 )
if (inc ! = sys.maxsize):
inc + = arr[i][ 1 ]
exc = findMinCostUtil(arr, X, n, dp, i + 1 )
dp[i][X] = min (inc, exc)
return dp[i][X]
def findMinCost(arr, X, n):
dp = [[sys.maxsize for i in range (X + 1 )] for j in range (n + 1 )]
ans = findMinCostUtil(arr, X, n, dp, 0 )
if (ans ! = sys.maxsize):
print (ans)
else :
print ( - 1 )
arr = [ [ 4 , 3 ], [ 3 , 2 ], [ 2 , 4 ], [ 1 , 3 ], [ 4 , 2 ] ]
X = 7
n = 5
findMinCost(arr, X, n)
|
C#
using System;
class GFG
{
static int findMinCostUtil( int [,] arr, int X, int n, int [,] dp, int i)
{
if (X <= 0)
return 0;
if (i >= n)
return Int32.MaxValue;
if (dp[i,X] != Int32.MaxValue)
return dp[i,X];
int inc = findMinCostUtil(arr, X - arr[i,0], n, dp, i + 1);
if (inc != Int32.MaxValue)
inc += arr[i,1];
int exc = findMinCostUtil(arr, X, n, dp, i + 1);
dp[i,X] = Math.Min(inc, exc);
return dp[i,X];
}
static void findMinCost( int [,] arr, int X, int n)
{
int [,] dp = new int [n + 1, X + 1];
for ( int i = 0; i <= n; i++) {
for ( int j = 0; j <= X; j++)
dp[i,j] = Int32.MaxValue;
}
int ans = findMinCostUtil(arr, X, n, dp, 0);
if (ans != Int32.MaxValue)
Console.WriteLine(ans);
else
Console.WriteLine(-1);
}
static void Main ()
{
int [,] arr = {
{ 4, 3 }, { 3, 2 },
{ 2, 4 }, { 1, 3 }, { 4, 2 }
};
int X = 7;
int n = 5;
findMinCost(arr, X, n);
}
}
|
Javascript
<script>
function findMinCostUtil(arr, X, n, dp, i)
{
if (X <= 0)
return 0;
if (i >= n)
return Number.MAX_VALUE;
if (dp[i][X] != Number.MAX_VALUE)
return dp[i][X];
let inc = findMinCostUtil(arr, X - arr[i][0], n, dp, i + 1);
if (inc != Number.MAX_VALUE)
inc += arr[i][1];
let exc = findMinCostUtil(arr, X, n, dp, i + 1);
dp[i][X] = Math.min(inc, exc);
return dp[i][X];
}
function findMinCost(arr, X, n)
{
let dp = new Array(n + 1);
for (let i = 0; i <= n; i++)
{
dp[i] = new Array(X + 1);
for (let j = 0; j <= X; j++)
dp[i][j] = Number.MAX_VALUE;
}
let ans = findMinCostUtil(arr, X, n, dp, 0);
if (ans != Number.MAX_VALUE)
document.write(ans);
else
document.write(-1);
}
let arr = [ [ 4, 3 ], [ 3, 2 ],
[ 2, 4 ], [ 1, 3 ],
[ 4, 2 ] ];
let X = 7;
let n = 5;
findMinCost(arr, X, n);
</script>
|
Time Complexity: O(N * X)
Auxiliary Space: O(N * X)
Efficient approach: Using the DP Tabulation method ( Iterative approach )
The approach to solving this problem is same but DP tabulation(bottom-up) method is better then Dp + memorization(top-down) because the memorization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a 2D array dp[][] of size (n+1) x (X+1), where n is the size of the given array arr[] and X is the minimum number of chocolates to be bought.
- Initialize all the entries of the array with INT_MAX to mark them as unreachable.
- Set the base case of dp[0][0] as 0, as the minimum cost to buy 0 chocolates is 0.
- Iterate through the array arr[] and through the range of X.
- Update dp[i][j] as the minimum of dp[i-1][j] and dp[i-1][j-arr[i-1].first] + arr[i-1].second if j >= arr[i-1].first, where arr[i-1].first is the cost of the ith chocolate and arr[i-1].second is the sweetness level of the ith chocolate.
- Print the minimum cost as dp[n][X] if it is not equal to INT_MAX, else print -1.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
void findMinCost(pair< int , int > arr[], int X, int n)
{
int dp[n + 1][X + 1];
for ( int i = 0; i <= n; i++) {
for ( int j = 0; j <= X; j++) {
dp[i][j] = INT_MAX;
}
}
dp[0][0] = 0;
for ( int i = 1; i <= n; i++) {
for ( int j = 0; j <= X; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= arr[i - 1].first) {
int inc = dp[i - 1][j - arr[i - 1].first];
if (inc != INT_MAX) {
dp[i][j] = min(dp[i][j],
inc + arr[i - 1].second);
}
}
}
}
if (dp[n][X] != INT_MAX) {
cout << dp[n][X];
}
else {
cout << -1;
}
}
int main()
{
pair< int , int > arr[] = {
{ 4, 3 }, { 3, 2 }, { 2, 4 }, { 1, 3 }, { 4, 2 }
};
int X = 7;
int n = sizeof (arr) / sizeof (arr[0]);
findMinCost(arr, X, n);
return 0;
}
|
Java
import java.util.*;
public class Main {
static void findMinCost(Pair[] arr, int X, int n)
{
int [][] dp = new int [n + 1 ][X + 1 ];
for ( int i = 0 ; i <= n; i++) {
for ( int j = 0 ; j <= X; j++) {
dp[i][j] = Integer.MAX_VALUE;
}
}
dp[ 0 ][ 0 ] = 0 ;
for ( int i = 1 ; i <= n; i++) {
for ( int j = 0 ; j <= X; j++) {
dp[i][j] = dp[i - 1 ][j];
if (j >= arr[i - 1 ].first) {
int inc = dp[i - 1 ][j - arr[i - 1 ].first];
if (inc != Integer.MAX_VALUE) {
dp[i][j] = Math.min(dp[i][j], inc + arr[i - 1 ].second);
}
}
}
}
if (dp[n][X] != Integer.MAX_VALUE) {
System.out.println(dp[n][X]);
} else {
System.out.println(- 1 );
}
}
public static void main(String[] args) {
Pair[] arr = { new Pair( 4 , 3 ), new Pair( 3 , 2 ), new Pair( 2 , 4 ), new Pair( 1 , 3 ), new Pair( 4 , 2 ) };
int X = 7 ;
int n = arr.length;
findMinCost(arr, X, n);
}
static class Pair {
int first, second;
Pair( int a, int b) {
first = a;
second = b;
}
}
}
|
Python3
def findMinCost(arr, X, n):
dp = [[ float ( 'inf' ) for j in range (X + 1 )] for i in range (n + 1 )]
dp[ 0 ][ 0 ] = 0
for i in range ( 1 , n + 1 ):
for j in range (X + 1 ):
dp[i][j] = dp[i - 1 ][j]
if j > = arr[i - 1 ][ 0 ]:
inc = dp[i - 1 ][j - arr[i - 1 ][ 0 ]]
if inc ! = float ( 'inf' ):
dp[i][j] = min (dp[i][j], inc + arr[i - 1 ][ 1 ])
if dp[n][X] ! = float ( 'inf' ):
print (dp[n][X])
else :
print ( - 1 )
if __name__ = = '__main__' :
arr = [( 4 , 3 ), ( 3 , 2 ), ( 2 , 4 ), ( 1 , 3 ), ( 4 , 2 )]
X = 7
n = len (arr)
findMinCost(arr, X, n)
|
C#
using System;
public class Program
{
public static void FindMinCost(Tuple< int , int >[] arr, int X, int n)
{
int [,] dp = new int [n + 1, X + 1];
for ( int i = 0; i <= n; i++)
{
for ( int j = 0; j <= X; j++)
{
dp[i, j] = int .MaxValue;
}
}
dp[0, 0] = 0;
for ( int i = 1; i <= n; i++)
{
for ( int j = 0; j <= X; j++)
{
dp[i, j] = dp[i - 1, j];
if (j >= arr[i - 1].Item1)
{
int inc = dp[i - 1, j - arr[i - 1].Item1];
if (inc != int .MaxValue)
{
dp[i, j] = Math.Min(dp[i, j], inc + arr[i - 1].Item2);
}
}
}
}
if (dp[n, X] != int .MaxValue)
{
Console.WriteLine(dp[n, X]);
}
else
{
Console.WriteLine(-1);
}
}
public static void Main()
{
Tuple< int , int >[] arr = {
Tuple.Create(4, 3), Tuple.Create(3, 2), Tuple.Create(2, 4), Tuple.Create(1, 3), Tuple.Create(4, 2)
};
int X = 7;
int n = arr.Length;
FindMinCost(arr, X, n);
}
}
|
Javascript
function findMinCost(arr, X, n)
{
const dp = new Array(n + 1).fill().map(() => new Array(X + 1).fill(Infinity));
dp[0][0] = 0;
for (let i = 1; i <= n; i++) {
for (let j = 0; j <= X; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= arr[i - 1][0]) {
const inc = dp[i - 1][j - arr[i - 1][0]];
if (inc !== Infinity) {
dp[i][j] = Math.min(dp[i][j], inc + arr[i - 1][1]);
}
}
}
}
if (dp[n][X] !== Infinity) {
console.log(dp[n][X]);
} else {
console.log(-1);
}
}
const arr = [
[4, 3],
[3, 2],
[2, 4],
[1, 3],
[4, 2],
];
const X = 7;
const n = arr.length;
findMinCost(arr, X, n);
|
Time Complexity: O(N*X)
Auxiliary Space: O(N*X)
Last Updated :
13 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...