Fractional Knapsack Problem

Learn via video course
FREE
View all courses
DSA Problem Solving for Interviews using Java
DSA Problem Solving for Interviews using Java
by Jitender Punia
1000
4.9
Start Learning
DSA Problem Solving for Interviews using Java
DSA Problem Solving for Interviews using Java
by Jitender Punia
1000
4.9
Start Learning
Topics Covered

Overview

The Knapsack problem is a class of optimization problems in which we have to find the maximal answer among all the various possibilities given in the question. There are three types of knapsack problems i.e.i.e. 0-1 Knapsack, Fractional Knapsack, and Unbounded Knapsack. In this article, we will be seeing the fractional knapsack Problem in detail.

Introduction to Fractional Knapsack Problem

Given two arrays named value and weight of size nn each, where value[i] represents the value and weight[i] represents the weight associated with the ithi^{th} item. Also, we have been provided a knapsack with a maximum capacity of W.

The task is to pick some items (possibly all of them) such that the sum of values of all the items is maximized and the sum of weights of all the items is at most W.

As the name Fractional suggests, here we are allowed to take a fraction of an item. For example, if the weight of an ithi^{th} item is xx units, then we can have the following choices :

  1. Do not take any fraction of the ithi^{th} item.
  2. Take the item as a whole.
  3. Take any integer weight of the ithi^{th} item i.e.i.e. For an item of weight 2020 Kg. we can either take 11 Kg, 22 Kg, ..., or 1919 Kg but we are not allowed to take 1.21.2 Kg or 5.75.7 Kg.

Note that if we are taking a fraction of an item, we get the value in the same fraction.

Example

Input :

Output :

Explanation :
Let's say we take the 1st1^{st} item as a whole, so we obtain a value of40and the capacity of the knapsack is now reduced to50. Then we pick the 3rd3^{rd} item as a whole, after which we obtain a value of120and the capacity of the knapsack is now reduced to30.

Now we take 30 Kg. of the 4th4^{th} item, which will add 7050×30=42\frac{70}{50} \times 30 = 42 to our value due to which we obtained a value of 162 and we are left with no space in the knapsack hence we can conclude the result to be 162.

It can be proved that there is no other choice of picking item(s) such that the value of the chosen item(s) exceeds 162.

Techniques to Solve the Fractional Knapsack Problem

Brute Force Approach

Since for an item of weight xx, we have x+1x+1 choices i.e.i.e. taking 0 Kg. of the item, taking 1 Kg. of the item, taking 2 Kg. of the item, ...., taking xx Kg. of the item. Therefore, with the brute force approach, we can check the value of all the possibilities from the set of items provided.

As discussed above, for the ithi^{th} item we have weighti+1weight_i + 1 choices, and hence the total number of possibilities is KaTeX parse error: $ within math mode. Therefore, the time complexity of the brute force approach is O(i=0n1(weighti+1))O(\prod_{i=0}^{n-1} (\text{weight}_i + 1))

Example :

Let's say we have the following items :

Item no.WeightValue
113
216
315

And a knapsack with a capacity of 3.

So, as per the brute force algorithm, we can have the following choices : In the below-given matrix, the value in the celli,j\text{cell}_{i, j} denotes the amount of weight of jthj^{th} item we are taking in the ithi^{th} choice.

Item1\text{Item}_1Item2\text{Item}_2Item3\text{Item}_3Total Value
0000
0015
0106
01111
1003
1018
1109
11114

The highest possible value we can obtain is 14 i.e.i.e. by picking the 1 Kg. of all the items.

Greedy Approach

We have seen that the brute force approach works every time but on a reasonable large input, it will take a very huge amount of time to calculate the answer.

So, we can opt for a greedy algorithm. We can have several potentially correct strategies, some of the obvious ones are :

  1. Picking the items with the largest values first.
  2. Picking the items with the lowest weights first.
  3. Picking the items based on some sort of ratio among their values and weights.

In the next section of this article, we will see which of the above approach is correct and the reason behind their correctness.

Example of Solving a Fractional Knapsack Problem Using Three Approaches

Let's say we have the following input :

Items :

Item No.WeightValue
11040
23020
32080
45070
52050

Capacity (W) : 70

Approach - 1 : Picking Items with the Largest Value

Item No.WeightValueRemaining Space
3208070 - 20 = 50
4507050 - 50 = 0

Using the approach we can obtain a value of 80+70=15080+70=150

Approach - 2 : Picking Items with the Smallest Weight

Item No.WeightValueRemaining Space
1104070 - 10 = 60
3208060 - 20 = 40
5205040 - 20 = 20
230203020=13.33\frac{20}{30} * 20 = 13.3320 - 20 = 0

Using the approach we can obtain a value of 80+40+50+13.33=183.3380+40+50+13.33=183.33

Approach - 3 : Picking Items Based on Ratio

As per this approach, we will find the value obtained per unit weight for all items. And we will take the items with the largest value per unit weight first. So we will have our input modified to :

Item No.WeightValueValueWeight\frac{Value}{Weight}
110404010=4\frac{40}{10} = 4
230202030=0.66\frac{20}{30} = 0.66
320808020=4\frac{80}{20} = 4
450707050=1.4\frac{70}{50} = 1.4
520505020=1.5\frac{50}{20} = 1.5

Now picking items as follows :

Item No.WeightValueRemaining Space
1104070 - 10 = 60
3208060 - 20 = 40
5205040 - 20 = 20
450705020=28\frac{70}{50} * 20 = 2840 - 20 = 0

Using the approach we can obtain a value of 80+40+50+28=19880+40+50+28=198

We can see that by following the third approach we can obtain the maximum value. This is because in other approaches we were giving importance to only one parameter but in the third approach, we considered the ratio of both to obtain the maximal value.

Also, another possible way is to find the ratio of Weight Gained Per unit value (which is reciprocal of the current ratio), and then choose items in ascending order of the ratio's value.

Greedy Algorithm

As seen in the previous section, for each item we will calculate the ratio of value to its weight i.e.valueiweightii.e. \frac{value_i}{weight_i} which denotes the value obtained per unit weight.

Now to get the maximal value, we will sort the items in the descending order of the ratio so that items with greater ratio values are picked before items with a comparatively smaller ratio.

While picking an item, we will check if it is possible to take it as a whole or not because we are constrained by the capacity of the knapsack. So, if it is not possible to pick the item as a whole, we will pick as much weight of the item as we can.

The algorithm is as follows :

  • Sort the items in descending order using a custom comparator based on the value per unit weight ratio.
  • Declare a variable of floating-point type, ans, and initialize it with 0.
  • Iterate from i=0i = 0 To i=i = Item.length 1- 1 and do the following :
    • If it is possible to take the item[i] as a whole do the following :
      • Add value[i] to the ans, because we have picked this item as a whole.
      • Subtract weight[i] from the Capacity, because picking this item will reduce the capacity.
    • Otherwise do the following :
      • Let's say you are left with capacity yy.
      • Add value[i]weight[i]×y\frac{value[i]}{weight[i]} \times y to ans.
      • Subtract yy from Capacity.
      • Terminate the loop as the Knapsack is full.
  • Return the result i.e.i.e. ans.

Pseudocode


Java Implementation

Output :


C++ Implementation

Output :


Python Implementation

Output :


C# Implementation

Output :

Complexity Analysis

  • Time Complexity :
    Sorting the item set will require at least O(nlogn)O(n \log{n}) time, and Iterating over the sorted item set will require O(n)O(n) time. Hence the overall time complexity is O(nlogn+n)O(nlogn)O(n\log{n} + n) \simeq O(n\log{n})

  • Space Complexity :
    Doesn't matter which sorting algorithm we use for sorting, it will require O(n)O(n) extra space because we need to combine value and weight arrays using a 2-D array/list to sort them. Hence the overall space complexity is O(n)O(n).

Bonus Tip

We have seen the time complexity to be O(nlogn)O(n\log{n}) but in the best case, we can optimize it further to O(n)O(n).

Let's see how :

If the capacity of our knapsack is greater than or equal to the sum of the weights of all the items, we do not need to sort items. Instead, we can select all the items available because we have hefty space to accommodate all of them.

So, in this case, we just need to find the sum of all the values which will require O(n)O(n) time.

Conclusion

  • In the fractional knapsack problem, we are allowed to split the items in fractions, unlike the 0-1 Knapsack problem where it is prohibited to split the items.
  • Checking for all the possible choices of picking items works well but requires a huge amount of time.
  • The Greedy approach uses the value per unit weight ratio of items to select the best choices.