Skip to content

Commit 91d93f2

Browse files
authored
Create README.md
1 parent 1fb3c1e commit 91d93f2

File tree

1 file changed

+247
-0
lines changed
  • 25 - Greedy Algorithm Problems/09 - Fractional Knapsack

1 file changed

+247
-0
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
<h1 align="center">Fractional - Knapsack</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Fractional Knapsack](https://www.geeksforgeeks.org/problems/fractional-knapsack-1587115620/1?itm_source=geeksforgeeks&itm_medium=article&itm_campaign=practice_card)
6+
7+
![image](https://github.com/user-attachments/assets/fb79717a-26f3-4381-af40-9771c1429716)
8+
9+
### Problem Explanation
10+
The problem you're referring to is the **Fractional Knapsack Problem**, which is a classic problem in optimization. Here, you are given a knapsack with a certain capacity and a set of items. Each item has a value and a weight. The goal is to maximize the total value in the knapsack without exceeding its capacity.
11+
12+
**Key points:**
13+
- You can take fractions of items (i.e., you don’t have to take the whole item if it exceeds the remaining capacity).
14+
- The challenge is to maximize the total value without exceeding the knapsack’s capacity.
15+
16+
### Problem Description:
17+
You are given:
18+
1. A list of `n` items, each with a `value[i]` and `weight[i]`.
19+
2. A `capacity` of the knapsack.
20+
21+
You are required to fill the knapsack in such a way that the **total value is maximized**, while not exceeding the knapsack’s capacity. You can take fractions of the items if necessary.
22+
23+
### Example:
24+
**Input:**
25+
- `value[] = {60, 100, 120}`
26+
- `weight[] = {10, 20, 30}`
27+
- `capacity = 50`
28+
29+
**Steps to solve the problem:**
30+
1. First, calculate the **value per unit weight** for each item:
31+
- Item 1: ( frac{60}{10} = 6 )
32+
- Item 2: ( frac{100}{20} = 5 )
33+
- Item 3: ( frac{120}{30} = 4 )
34+
35+
2. Sort the items by **value per unit weight** in descending order:
36+
- Sorted order: Item 1 → Item 2 → Item 3
37+
38+
3. Fill the knapsack with items in this sorted order, and take fractions as needed:
39+
- First, take the full Item 1 (weight = 10, value = 60). Remaining capacity = 50 - 10 = 40.
40+
- Next, take the full Item 2 (weight = 20, value = 100). Remaining capacity = 40 - 20 = 20.
41+
- Finally, take a fraction of Item 3 (weight = 20, value = 120). We can take only 20 units from this item, which gives a fraction of ( frac{20}{30} times 120 = 80 ).
42+
43+
4. The total value of the knapsack is ( 60 + 100 + 80 = 240 ).
44+
45+
**Output:** The maximum value that can be obtained is 240.
46+
47+
### Greedy Approach (Step by Step):
48+
49+
The **Greedy Approach** for solving the Fractional Knapsack Problem can be summarized in the following steps. Let’s break down the greedy approach used in the code you previously shared:
50+
51+
### 1. **Calculate Value per Unit Weight:**
52+
For each item, calculate the value-to-weight ratio. This ratio helps determine the **"value density"** of the item (how much value we get per unit of weight).
53+
54+
For item (i):
55+
`
56+
{value per unit weight} = frac{{value}[i]}{{weight}[i]}
57+
`
58+
59+
**Example:**
60+
```cpp
61+
val = [60, 100, 120`wt = [10, 20, 30
62+
````
63+
For each item:
64+
- Item 1: ( frac{60}{10} = 6.0 )
65+
- Item 2: ( frac{100}{20} = 5.0 )
66+
- Item 3: ( frac{120}{30} = 4.0 )
67+
68+
### 2. **Sort Items by Value per Unit Weight:**
69+
Sort the items in descending order based on their value per unit weight. This ensures that we prioritize the most valuable items (i.e., those that give the most value per unit weight).
70+
71+
Sorted items by value per unit weight:
72+
- Item 1 (6.0)
73+
- Item 2 (5.0)
74+
- Item 3 (4.0)
75+
76+
### 3. **Greedily Select Items:**
77+
Start filling the knapsack from the sorted list, taking items in the order of highest value per unit weight.
78+
79+
#### **a. Take Full Items (if capacity allows):**
80+
If the knapsack has enough capacity to accommodate the current item, take the full item, and reduce the remaining capacity accordingly.
81+
82+
#### **b. Take Fraction of Item (if capacity doesn’t allow):**
83+
If the knapsack doesn’t have enough capacity to take the full item, take the fraction of the item that can fit in the remaining capacity. The value added will be proportional to the weight that we take.
84+
85+
For each item, we:
86+
- If the item’s weight is less than or equal to the remaining capacity, we add the full value of the item.
87+
- If the item’s weight is greater than the remaining capacity, we add the fractional value based on the remaining capacity.
88+
89+
### 4. **Return the Total Value:**
90+
Once the knapsack is filled, return the total value accumulated.
91+
92+
## Problem Solution
93+
```cpp
94+
class Solution {
95+
public:
96+
// Function to solve the Fractional Knapsack problem
97+
double fractionalKnapsack(vector<int>& val, vector<int>& wt, int capacity) {
98+
// Create a vector to store pairs where each pair consists of the per unit value
99+
// and the corresponding (value, weight) pair for each item
100+
vector<pair<double, pair<int, int>>> v;
101+
102+
// Step 1: Calculate the per unit value (value/weight) for each item and store it
103+
for(int i = 0; i < val.size(); i++){
104+
double perUnitValue = 1.0 * val[i] / wt[i]; // Calculate per unit value for the item
105+
v.push_back({perUnitValue, {val[i], wt[i]}}); // Store the per unit value along with the (value, weight) pair
106+
}
107+
108+
// Step 2: Sort the vector 'v' in decreasing order based on per unit value
109+
sort(v.begin(), v.end(), [](pair<double, pair<int, int>>& a, pair<double, pair<int, int>>& b){
110+
return a.first > b.first; // Comparator to sort by per unit value in descending order
111+
});
112+
113+
// Step 3: Initialize the total value of the knapsack to 0
114+
double totalValue = 0.0;
115+
116+
// Step 4: Start filling the knapsack
117+
for(int i = 0; i < val.size(); i++){
118+
int currentWeight = v[i].second.second; // Get the weight of the current item
119+
int currentValue = v[i].second.first; // Get the value of the current item
120+
double perUnitValue = v[i].first; // Get the per unit value of the current item
121+
122+
// Step 5: Check if the current item can be fully added to the knapsack
123+
if(capacity >= currentWeight) {
124+
totalValue += currentValue; // Add the full value of the item
125+
capacity -= currentWeight; // Decrease the remaining capacity of the knapsack
126+
} else {
127+
// If the current item cannot be fully added, add the fractional part of it
128+
totalValue += capacity * perUnitValue; // Add the value for the fractional weight
129+
break; // Once the knapsack is full, break out of the loop
130+
}
131+
}
132+
133+
// Step 6: Return the total value of the knapsack
134+
return totalValue;
135+
}
136+
};
137+
138+
```
139+
140+
## Problem Solution Explanation
141+
#### **Step 1: Initialize a vector `v`**
142+
```cpp
143+
vector<pair<double, pair<int, int>>> v;
144+
```
145+
- **Purpose**: `v` is a vector of pairs where each element is a pair of:
146+
- `double`: the per unit value (value/weight) of an item.
147+
- `pair<int, int>`: contains the value and weight of the item.
148+
149+
#### **Step 2: Calculate the per unit value for each item**
150+
```cpp
151+
for(int i = 0; i < val.size(); i++){
152+
double perUnitValue = 1.0 * val[i] / wt[i]; // Calculate per unit value for the item
153+
v.push_back({perUnitValue, {val[i], wt[i]}}); // Store the per unit value along with the (value, weight) pair
154+
}
155+
```
156+
- **Purpose**: This loop calculates the **value per unit weight** for each item.
157+
- For each item, `perUnitValue` is calculated as the value of the item divided by its weight (`val[i] / wt[i]`).
158+
- The pair is then pushed into the vector `v` with the first element as the per unit value and the second element as the pair `(value, weight)`.
159+
160+
**Example**:
161+
Let’s assume we have:
162+
163+
```cpp
164+
val = [60, 100, 120`wt = [10, 20, 30
165+
````
166+
For each item, the per unit value would be:
167+
- Item 1: ( frac{60}{10} = 6.0 )
168+
- Item 2: ( frac{100}{20} = 5.0 )
169+
- Item 3: ( frac{120}{30} = 4.0 )
170+
171+
`v` will look like this after the loop:
172+
173+
```cpp
174+
v = [(6.0, (60, 10)), (5.0, (100, 20)), (4.0, (120, 30))
175+
````
176+
177+
#### **Step 3: Sort items by per unit value in descending order**
178+
```cpp
179+
sort(v.begin(), v.end(), [](pair<double, pair<int, int>>& a, pair<double, pair<int, int>>& b){
180+
return a.first > b.first; // Comparator to sort by per unit value in descending order
181+
});
182+
```
183+
- **Purpose**: Sort the vector `v` in **descending order** of the per unit value. This ensures that we first consider the most valuable items (items that give the most value per unit of weight).
184+
- A lambda function is used as the comparator to sort by the first element of each pair (`a.first > b.first`), which is the per unit value.
185+
186+
**Example**:
187+
After sorting, `v` will look like this:
188+
```cpp
189+
v = [(6.0, (60, 10)), (5.0, (100, 20)), (4.0, (120, 30))
190+
````
191+
192+
#### **Step 4: Initialize the total value of the knapsack**
193+
```cpp
194+
double totalValue = 0.0;
195+
```
196+
- **Purpose**: Initialize `totalValue` to 0. This variable will store the accumulated value of the items placed in the knapsack.
197+
198+
#### **Step 5: Start filling the knapsack**
199+
```cpp
200+
for(int i = 0; i < val.size(); i++){
201+
int currentWeight = v[i].second.second; // Get the weight of the current item
202+
int currentValue = v[i].second.first; // Get the value of the current item
203+
double perUnitValue = v[i].first; // Get the per unit value of the current item
204+
```
205+
- **Purpose**: Iterate through each item in the sorted vector `v`. For each item, extract the weight (`currentWeight`), value (`currentValue`), and per unit value (`perUnitValue`).
206+
207+
**Example**:
208+
- For the first item in the sorted vector `v`:
209+
- `currentWeight = 10`, `currentValue = 60`, `perUnitValue = 6.0`.
210+
211+
#### **Step 6: Add items to the knapsack**
212+
```cpp
213+
if(capacity >= currentWeight) {
214+
totalValue += currentValue; // Add the full value of the item
215+
capacity -= currentWeight; // Decrease the remaining capacity of the knapsack
216+
} else {
217+
// If the current item cannot be fully added, add the fractional part of it
218+
totalValue += capacity * perUnitValue; // Add the value for the fractional weight
219+
break; // Once the knapsack is full, break out of the loop
220+
}
221+
```
222+
- **Purpose**: Check if the current item can be fully added to the knapsack based on the remaining capacity:
223+
- If the current item’s weight is less than or equal to the remaining capacity of the knapsack, add the full value of the item and update the remaining capacity.
224+
- If the item’s weight is more than the remaining capacity, add only the fractional value (based on how much of the item can fit) and then stop since the knapsack is full.
225+
226+
**Example**:
227+
Let’s assume the capacity of the knapsack is 50.
228+
- For the first item (weight = 10, value = 60), we can add the full item:
229+
- `totalValue += 60`, and `capacity -= 10``totalValue = 60`, `capacity = 40`.
230+
- For the second item (weight = 20, value = 100), we can add the full item:
231+
- `totalValue += 100`, and `capacity -= 20``totalValue = 160`, `capacity = 20`.
232+
- For the third item (weight = 30, value = 120), we can add only a fraction (capacity = 20):
233+
- `totalValue += 20 * 4.0 = 80`, and the knapsack is full (`capacity = 0`).
234+
235+
#### **Step 7: Return the total value**
236+
```cpp
237+
return totalValue;
238+
```
239+
- **Purpose**: Return the total accumulated value of the items in the knapsack.
240+
241+
### Time Complexity:
242+
- **Sorting the vector** takes (O(n log n)), where (n) is the number of items.
243+
- **Iterating through the items** takes (O(n)).
244+
Thus, the overall time complexity is dominated by the sorting step, so the time complexity is **(O(n log n))**.
245+
246+
### Space Complexity:
247+
- The space complexity is (O(n)) because we store the items and their per unit values in the vector `v`.

0 commit comments

Comments
 (0)