You are given a bag of size w kg and you are provided costs of packets different weights of oranges in array cost[], find the minimum total cost to buy exactly w kg oranges.
- The cost of 1 kg orange is present at index 0 and in general arr[i] has cost of (i+1) kg orange..
- cost[i] = -1 means that 'i+1' kg packet of orange is unavailable
- If it is not possible to buy exactly w kg oranges then print -1. It may be assumed that there is an infinite supply of all available packet types.
Examples:
Input : w = 5, cost[] = [20, 10, 4, 50, 100]
Output : 14
Explanation: We can choose two oranges to minimize cost. First orange of 2 Kg and cost 10. Second orange of 3 Kg and cost 4.Input : w = 5, cost[] = [1, 10, 4, 50, 100]
Output : 5
Explanation : We can choose five oranges of weight 1 kg.Input : w = 5, cost[] = [1, 2, 3, 4, 5]
Output : 5
Explanation : Costs of 1, 2, 3, 4 and 5 kg packets are 1, 2, 3, 4 and 5 Rs respectively. We choose packet of 5 kg having cost 5 for minimum cost to get 5 Kg oranges.Input : w = 5, cost[] = [-1, -1, 4, 5, -1 ]
Output : -1
Explanation: Packets of size 1, 2 and 5 kg are unavailable because they have cost -1. Cost of 3 kg packet is 4 Rs and of 4 kg is 5 Rs. Here we have only weights 3 and 4 so by using these two we can not make exactly W kg weight, therefore answer is -1.
Table of Content
Using Unbounded Knapsack - O(n * w) Time and O(n * w) Space
This problem is can be reduced to Unbounded Knapsack. So in the cost array, we first ignore those packets which are not available i.e; cost is -1 and then traverse the cost array and create two array val[] for storing the cost of 'i' kg packet of orange and wt[] for storing weight of the corresponding packet. Suppose cost[i] = 50 so the weight of the packet will be i and the cost will be 50.
- Create matrix min_cost[n+1][W+1], where n is number of distinct weighted packets of orange and W is the maximum capacity of the bag.
- Initialize the 0th row with INF (infinity) and 0th Column with 0.
- Now fill the matrix: if wt[i-1] > j then min_cost[i][j] = min_cost[i-1][j]. Else min_cost[i][j] = min(min_cost[i-1][j], val[i-1] + min_cost[i][j-wt[i-1]]);
- If min_cost[n][W] == INF then output will be -1 because this means that we can not make weight W by using these weights else output will be min_cost[n][W].
Below is the implementation of the above algorithm:
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
// cost[] initial cost array including unavailable packet
// w capacity of bag
int minimumCost(int w, vector<int> &cost)
{
// val[] and wt[] arrays
// val[] array to store cost of 'i' kg packet of orange
// wt[] array weight of packet of orange
vector<int> val, wt;
int n = cost.size();
// traverse the original cost[] array and skip
// unavailable packets and make val[] and wt[]
// array. size variable tells the available number
// of distinct weighted packets
for (int i = 0; i < n; i++)
{
if (cost[i] != -1)
{
val.push_back(cost[i]);
wt.push_back(i + 1);
}
}
int size = val.size();
const int INF = 1e9;
// DP table
vector<vector<int>> min_cost(size + 1, vector<int>(w + 1, INF));
// fill 0th column with 0
for (int i = 0; i <= size; i++)
min_cost[i][0] = 0;
// now check for each weight one by one and fill the
// matrix according to the condition
for (int i = 1; i <= size; i++)
{
for (int j = 1; j <= w; j++)
{
// wt[i-1] > j means capacity of bag is
// less than weight of item
if (wt[i - 1] > j)
min_cost[i][j] = min_cost[i - 1][j];
// here we check we get minimum cost either
// by including it or excluding it
else
min_cost[i][j] = min(min_cost[i - 1][j],
min_cost[i][j - wt[i - 1]] + val[i - 1]);
}
}
// exactly weight w can not be made by given weights
return (min_cost[size][w] >= INF) ? -1 : min_cost[size][w];
}
// Driver code
int main()
{
int w = 5;
vector<int> cost = {1, 2, 3, 4, 5};
cout << minimumCost(w, cost);
return 0;
}
import java.util.*;
class GFG {
// cost[] initial cost array including unavailable packet
// w capacity of bag
static int minimumCost(int w, int[] cost)
{
// val[] and wt[] arrays
// val[] array to store cost of 'i' kg packet of orange
// wt[] array weight of packet of orange
List<Integer> val = new ArrayList<>();
List<Integer> wt = new ArrayList<>();
int n = cost.length;
// traverse the original cost[] array and skip
// unavailable packets and make val[] and wt[]
// array. size variable tells the available number
// of distinct weighted packets
for (int i = 0; i < n; i++)
{
if (cost[i] != -1)
{
val.add(cost[i]);
wt.add(i + 1);
}
}
int size = val.size();
int INF = (int)1e9;
// DP table
int[][] min_cost = new int[size + 1][w + 1];
for (int i = 0; i <= size; i++)
Arrays.fill(min_cost[i], INF);
// fill 0th column with 0
for (int i = 0; i <= size; i++)
min_cost[i][0] = 0;
// now check for each weight one by one and fill the
// matrix according to the condition
for (int i = 1; i <= size; i++)
{
for (int j = 1; j <= w; j++)
{
// wt[i-1] > j means capacity of bag is
// less than weight of item
if (wt.get(i - 1) > j)
min_cost[i][j] = min_cost[i - 1][j];
// here we check we get minimum cost either
// by including it or excluding it
else
min_cost[i][j] = Math.min(min_cost[i - 1][j],
min_cost[i][j - wt.get(i - 1)] + val.get(i - 1));
}
}
// exactly weight w can not be made by given weights
return (min_cost[size][w] >= INF) ? -1 : min_cost[size][w];
}
// Driver code
public static void main(String[] args)
{
int w = 5;
int[] cost = {1, 2, 3, 4, 5};
System.out.println(minimumCost(w, cost));
}
}
# cost[] initial cost array including unavailable packet
# w capacity of bag
def minimumCost(w, cost):
# val[] and wt[] arrays
# val[] array to store cost of 'i' kg packet of orange
# wt[] array weight of packet of orange
val = []
wt = []
n = len(cost)
# traverse the original cost[] array and skip
# unavailable packets and make val[] and wt[]
# array. size variable tells the available number
# of distinct weighted packets
for i in range(n):
if cost[i] != -1:
val.append(cost[i])
wt.append(i + 1)
size = len(val)
INF = int(1e9)
# DP table
min_cost = [[INF] * (w + 1) for _ in range(size + 1)]
# fill 0th column with 0
for i in range(size + 1):
min_cost[i][0] = 0
# now check for each weight one by one and fill the
# matrix according to the condition
for i in range(1, size + 1):
for j in range(1, w + 1):
# wt[i-1] > j means capacity of bag is
# less than weight of item
if wt[i - 1] > j:
min_cost[i][j] = min_cost[i - 1][j]
# here we check we get minimum cost either
# by including it or excluding it
else:
min_cost[i][j] = min(min_cost[i - 1][j],
min_cost[i][j - wt[i - 1]] + val[i - 1])
# exactly weight w can not be made by given weights
return -1 if min_cost[size][w] >= INF else min_cost[size][w]
# Driver code
w = 5
cost = [1, 2, 3, 4, 5]
print(minimumCost(w, cost))
using System;
using System.Collections.Generic;
class GFG {
// cost[] initial cost array including unavailable packet
// w capacity of bag
static int minimumCost(int w, int[] cost)
{
List<int> val = new List<int>();
List<int> wt = new List<int>();
int n = cost.Length;
// traverse the original cost[] array and skip
// unavailable packets and make val[] and wt[]
for (int i = 0; i < n; i++)
{
if (cost[i] != -1)
{
val.Add(cost[i]);
wt.Add(i + 1);
}
}
int size = val.Count;
int INF = (int)1e9;
int[,] min_cost = new int[size + 1, w + 1];
for (int i = 0; i <= size; i++)
for (int j = 0; j <= w; j++)
min_cost[i, j] = INF;
// fill 0th column with 0
for (int i = 0; i <= size; i++)
min_cost[i, 0] = 0;
for (int i = 1; i <= size; i++)
{
for (int j = 1; j <= w; j++)
{
if (wt[i - 1] > j)
min_cost[i, j] = min_cost[i - 1, j];
else
min_cost[i, j] = Math.Min(min_cost[i - 1, j],
min_cost[i, j - wt[i - 1]] + val[i - 1]);
}
}
return (min_cost[size, w] >= INF) ? -1 : min_cost[size, w];
}
public static void Main()
{
int w = 5;
int[] cost = {1, 2, 3, 4, 5};
Console.WriteLine(minimumCost(w, cost));
}
}
// cost[] initial cost array including unavailable packet
// w capacity of bag
function minimumCost(w, cost)
{
let val = [];
let wt = [];
let n = cost.length;
// traverse the original cost[] array and skip
// unavailable packets and make val[] and wt[]
for (let i = 0; i < n; i++)
{
if (cost[i] !== -1)
{
val.push(cost[i]);
wt.push(i + 1);
}
}
let size = val.length;
const INF = 1e9;
let min_cost = Array.from({length: size + 1}, () => Array(w + 1).fill(INF));
// fill 0th column with 0
for (let i = 0; i <= size; i++)
min_cost[i][0] = 0;
for (let i = 1; i <= size; i++)
{
for (let j = 1; j <= w; j++)
{
if (wt[i - 1] > j)
min_cost[i][j] = min_cost[i - 1][j];
else
min_cost[i][j] = Math.min(min_cost[i - 1][j],
min_cost[i][j - wt[i - 1]] + val[i - 1]);
}
}
return (min_cost[size][w] >= INF) ? -1 : min_cost[size][w];
}
// Driver code
let w = 5;
let cost = [1, 2, 3, 4, 5];
console.log(minimumCost(w, cost));
Output
5
Space Optimization (1D DP - Unbounded Knapsack) - O(n * w) Time and O(w) Space
If we take a closer look at this problem, we may notice that this is a variation of Rod Cutting Problem. Instead of doing maximization, here we need to do minimization.
dp[i]: minimum cost to get exactly weighti- For every weight
i, try all packetswith weights less than it. - If packet is available and usable, update minimum cost
- This is Unbounded Knapsack because we can reuse packets
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
/* Returns the minimum cost to get exactly
w Kg with given cost[] array */
int minimumCost(int w, vector<int> &cost)
{
vector<int> dp(w + 1, INT_MAX);
int n = cost.size();
// base case
dp[0] = 0;
// Build the table dp[] in bottom up
// manner and return the last entry
for (int i = 1; i <= w; i++)
{
int min_cost = INT_MAX;
for (int j = 0; j < n; j++)
{
// cost[j] = -1 means unavailable
// j+1 is the weight of packet
if (cost[j] != -1 && (j + 1) <= i && dp[i - (j + 1)] != INT_MAX)
{
min_cost = min(min_cost, cost[j] + dp[i - (j + 1)]);
}
}
dp[i] = min_cost;
}
// exactly weight w cannot be made
return (dp[w] == INT_MAX) ? -1 : dp[w];
}
/* Driver code */
int main()
{
int w = 5;
vector<int> cost = {20, 10, 4, 50, 100};
cout << minimumCost(w, cost);
return 0;
}
import java.util.*;
class GFG {
/* Returns the minimum cost to get exactly
w Kg with given cost[] array */
static int minimumCost(int w, int[] cost)
{
int[] dp = new int[w + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
int n = cost.length;
// base case
dp[0] = 0;
// Build the table dp[] in bottom up
// manner and return the last entry
for (int i = 1; i <= w; i++)
{
int min_cost = Integer.MAX_VALUE;
for (int j = 0; j < n; j++)
{
// cost[j] = -1 means unavailable
// j+1 is the weight of packet
if (cost[j] != -1 && (j + 1) <= i && dp[i - (j + 1)] != Integer.MAX_VALUE)
{
min_cost = Math.min(min_cost, cost[j] + dp[i - (j + 1)]);
}
}
dp[i] = min_cost;
}
// exactly weight w cannot be made
return (dp[w] == Integer.MAX_VALUE) ? -1 : dp[w];
}
/* Driver code */
public static void main(String[] args)
{
int w = 5;
int[] cost = {20, 10, 4, 50, 100};
System.out.println(minimumCost(w, cost));
}
}
# Returns the minimum cost to get exactly
# w Kg with given cost[] array
def minimumCost(w, cost):
dp = [float('inf')] * (w + 1)
n = len(cost)
# base case
dp[0] = 0
# Build the table dp[] in bottom up
# manner and return the last entry
for i in range(1, w + 1):
min_cost = float('inf')
for j in range(n):
# cost[j] = -1 means unavailable
# j+1 is the weight of packet
if cost[j] != -1 and (j + 1) <= i and dp[i - (j + 1)] != float('inf'):
min_cost = min(min_cost, cost[j] + dp[i - (j + 1)])
dp[i] = min_cost
# exactly weight w cannot be made
return -1 if dp[w] == float('inf') else dp[w]
# Driver code
w = 5
cost = [20, 10, 4, 50, 100]
print(minimumCost(w, cost))
using System;
class GFG {
/* Returns the minimum cost to get exactly
w Kg with given cost[] array */
static int minimumCost(int w, int[] cost)
{
int[] dp = new int[w + 1];
for (int i = 0; i <= w; i++)
dp[i] = int.MaxValue;
int n = cost.Length;
// base case
dp[0] = 0;
for (int i = 1; i <= w; i++)
{
int min_cost = int.MaxValue;
for (int j = 0; j < n; j++)
{
if (cost[j] != -1 && (j + 1) <= i && dp[i - (j + 1)] != int.MaxValue)
{
min_cost = Math.Min(min_cost, cost[j] + dp[i - (j + 1)]);
}
}
dp[i] = min_cost;
}
return (dp[w] == int.MaxValue) ? -1 : dp[w];
}
public static void Main()
{
int w = 5;
int[] cost = {20, 10, 4, 50, 100};
Console.WriteLine(minimumCost(w, cost));
}
}
// Returns the minimum cost to get exactly
// w Kg with given cost[] array
function minimumCost(w, cost)
{
let dp = new Array(w + 1).fill(Infinity);
let n = cost.length;
// base case
dp[0] = 0;
for (let i = 1; i <= w; i++)
{
let min_cost = Infinity;
for (let j = 0; j < n; j++)
{
if (cost[j] !== -1 && (j + 1) <= i && dp[i - (j + 1)] !== Infinity)
{
min_cost = Math.min(min_cost, cost[j] + dp[i - (j + 1)]);
}
}
dp[i] = min_cost;
}
return (dp[w] === Infinity) ? -1 : dp[w];
}
// Driver code
let w = 5;
let cost = [20, 10, 4, 50, 100];
console.log(minimumCost(w, cost));
Output
14