Fractional Knapsack Algorithm
The Fractional Knapsack problem is an optimization problem where, given a set of items with specified weights and values, the goal is to maximize the total value within a weight limit by taking fractions of items. The greedy algorithm for this problem prioritizes items based on their value-to-weight ratio, allowing partial items to be selected if they maximize the overall value.
Characteristics:β
Greedy Approach:β
The algorithm selects items based on the highest value-to-weight ratio first. This ensures that the item providing the most value per unit weight is prioritized.
Optimal Solution:β
The greedy approach is optimal for the fractional knapsack problem, as allowing fractional parts of items enables us to maximize the value without exceeding the weight limit.
Steps Involved:β
Calculate Value-to-Weight Ratio: For each item, calculate the ratio of value to weight. This ratio will be used to prioritize item selection.
Sort Items by Ratio:β
Sort all items in descending order of their value-to-weight ratios to ensure the item providing the most value per unit weight is selected first.
Select Items Based on Weight Capacity:β
Traverse the sorted items, adding them fully if their weight doesn't exceed the remaining capacity. If an itemβs weight is too large, take only a fraction of it to fill the remaining capacity.
Problem Statement:β
Given a knapsack with a weight limit of W and a list of items, each with a value vi and weight wi, maximize the total value by selecting items (or fractions thereof) without exceeding W.
Time Complexity:β
Best, Average, and Worst Case: Where n is the number of items. Sorting items by their value-to-weight ratio takes O(n \log n) time.
Space Complexity:β
Space Complexity: Space is required to store item information and ratios.
Example: Consider a knapsack with a weight limit of W = 50 and the following items:
Items: {(value: 60, weight: 10), (value: 100, weight: 20), (value: 120, weight: 30)}
Sorted by ratio: {(value: 60, weight: 10), (value: 100, weight: 20), (value: 120, weight: 30)}
Step-by-Step Execution:
Add item with weight 10 (value-to-weight ratio 6): Total weight = 10, total value = 60.
Add item with weight 20 (value-to-weight ratio 5): Total weight = 30, total value = 160.
Add 2/3 of item with weight 30 (value-to-weight ratio 4): Total weight = 50, total value = 240.
Total Value: 240
C++ Implementation:
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Structure to represent an item
struct Item {
int value, weight;
};
// Comparator function to sort items by value-to-weight ratio
bool compare(Item a, Item b) {
double r1 = (double)a.value / a.weight;
double r2 = (double)b.value / b.weight;
return r1 > r2;
}
// Function to perform fractional knapsack
double fractionalKnapsack(int W, vector<Item>& items) {
// Sort items by descending value-to-weight ratio
sort(items.begin(), items.end(), compare);
int curWeight = 0;
double finalValue = 0.0;
for (auto item : items) {
if (curWeight + item.weight <= W) {
// If the item can be added fully
curWeight += item.weight;
finalValue += item.value;
} else {
// Take fraction of the item to fill the remaining capacity
int remainingWeight = W - curWeight;
finalValue += item.value * ((double)remainingWeight / item.weight);
break;
}
}
return finalValue;
}
int main() {
int W = 50; // Weight limit of the knapsack
vector<Item> items = { {60, 10}, {100, 20}, {120, 30} };
cout << "Maximum value we can obtain = " << fractionalKnapsack(W, items);
return 0;
}
Java Implementation:
java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Item {
int value, weight;
Item(int value, int weight) {
this.value = value;
this.weight = weight;
}
}
public class FractionalKnapsack {
// Comparator to sort items by value-to-weight ratio
static class ItemComparator implements Comparator<Item> {
public int compare(Item a, Item b) {
double r1 = (double) a.value / a.weight;
double r2 = (double) b.value / b.weight;
return Double.compare(r2, r1);
}
}
// Function to perform fractional knapsack
public static double fractionalKnapsack(int W, List<Item> items) {
Collections.sort(items, new ItemComparator());
int curWeight = 0;
double finalValue = 0.0;
for (Item item : items) {
if (curWeight + item.weight <= W) {
// Add full item
curWeight += item.weight;
finalValue += item.value;
} else {
// Add fraction of item
int remainingWeight = W - curWeight;
finalValue += item.value * ((double) remainingWeight / item.weight);
break;
}
}
return finalValue;
}
public static void main(String[] args) {
int W = 50; // Knapsack weight limit
List<Item> items = new ArrayList<>();
items.add(new Item(60, 10));
items.add(new Item(100, 20));
items.add(new Item(120, 30));
System.out.println("Maximum value we can obtain = " + fractionalKnapsack(W, items));
}
}
Summary: The Fractional Knapsack algorithm maximizes the total value of items in a knapsack with a weight limit by selecting items (or fractions of them) based on their value-to-weight ratio. This approach is widely applicable in resource allocation, inventory management, and financial investments. While the 0/1 knapsack problem is NP-complete, the fractional variant is solvable in polynomial time, making it efficient and optimal. The greedy algorithm ensures the maximum possible value within the given constraints.