给定n个物料的权重和值,我们需要将这些物料放在容量为W的背包中,以在背包中获得最大的总价值。
在0-1背包问题中,我们不允许破坏物品。我们要么拿走整个物品,要么不拿走。
Input:
Items as (value, weight) pairs
arr[] = {{60, 10}, {100, 20}, {120, 30}}
Knapsack Capacity, W = 50;
Output:
Maximum possible value = 240
by taking items of weight 10 and 20 kg and 2/3 fraction
of 30 kg. Hence total price will be 60+100+(2/3)(120) = 240
在分数背包中,我们可以破坏物品以最大化背包的总价值。我们可以破坏物品的问题也称为分数背包问题。
Input :
Same as above
Output :
Maximum possible value = 240
By taking full items of 10 kg, 20 kg and
2/3rd of last item of 30 kg
蛮力解决方案是尝试使用所有不同分数的所有可能子集,但这将花费大量时间。
一个有效的解决方案是使用贪婪方法。贪婪方法的基本思想是计算每个项目的比率值/权重,并根据该比率对项目进行排序。然后选择比例最高的项目并将其添加,直到我们不能整体添加下一个项目为止,最后添加尽可能多的下一个项目。这将永远是解决此问题的最佳方法。
与我们自己的比较函数的简单代码可以被写成如下,请参阅排序更紧密地函数,第三个参数排序函数是我们的比较函数按照非递减的顺序值/重量比,其排序的项目。
排序后,我们需要遍历这些项目并将其添加到满足上述条件的背包中。
下面是上述想法的实现:
C++
// C/C++ program to solve fractional Knapsack Problem
#include
using namespace std;
// Structure for an item which stores weight and
// corresponding value of Item
struct Item {
int value, weight;
// Constructor
Item(int value, int weight)
{
this->value=value;
this->weight=weight;
}
};
// Comparison function to sort Item according to val/weight
// ratio
bool cmp(struct Item a, struct Item b)
{
double r1 = (double)a.value / (double)a.weight;
double r2 = (double)b.value / (double)b.weight;
return r1 > r2;
}
// Main greedy function to solve problem
double fractionalKnapsack(int W, struct Item arr[], int n)
{
// sorting Item on basis of ratio
sort(arr, arr + n, cmp);
// Uncomment to see new order of Items with their
// ratio
/*
for (int i = 0; i < n; i++)
{
cout << arr[i].value << " " << arr[i].weight << " :
"
<< ((double)arr[i].value / arr[i].weight) <<
endl;
}
*/
int curWeight = 0; // Current weight in knapsack
double finalvalue = 0.0; // Result (value in Knapsack)
// Looping through all Items
for (int i = 0; i < n; i++) {
// If adding Item won't overflow, add it completely
if (curWeight + arr[i].weight <= W) {
curWeight += arr[i].weight;
finalvalue += arr[i].value;
}
// If we can't add current Item, add fractional part
// of it
else {
int remain = W - curWeight;
finalvalue += arr[i].value
* ((double)remain
/ (double)arr[i].weight);
break;
}
}
// Returning final value
return finalvalue;
}
// Driver code
int main()
{
int W = 50; // Weight of knapsack
Item arr[] = { { 60, 10 }, { 100, 20 }, { 120, 30 } };
int n = sizeof(arr) / sizeof(arr[0]);
// Function call
cout << "Maximum value we can obtain = "
<< fractionalKnapsack(W, arr, n);
return 0;
}
Java
// Java program to solve fractional Knapsack Problem
import java.util.Arrays;
import java.util.Comparator;
// Greedy approach
public class FractionalKnapSack {
// function to get maximum value
private static double getMaxValue(int[] wt, int[] val,
int capacity)
{
ItemValue[] iVal = new ItemValue[wt.length];
for (int i = 0; i < wt.length; i++) {
iVal[i] = new ItemValue(wt[i], val[i], i);
}
// sorting items by value;
Arrays.sort(iVal, new Comparator() {
@Override
public int compare(ItemValue o1, ItemValue o2)
{
return o2.cost.compareTo(o1.cost);
}
});
double totalValue = 0d;
for (ItemValue i : iVal) {
int curWt = (int)i.wt;
int curVal = (int)i.val;
if (capacity - curWt >= 0) {
// this weight can be picked while
capacity = capacity - curWt;
totalValue += curVal;
}
else {
// item cant be picked whole
double fraction
= ((double)capacity / (double)curWt);
totalValue += (curVal * fraction);
capacity
= (int)(capacity - (curWt * fraction));
break;
}
}
return totalValue;
}
// item value class
static class ItemValue {
Double cost;
double wt, val, ind;
// item value function
public ItemValue(int wt, int val, int ind)
{
this.wt = wt;
this.val = val;
this.ind = ind;
cost = new Double((double)val / (double)wt);
}
}
// Driver code
public static void main(String[] args)
{
int[] wt = { 10, 40, 20, 30 };
int[] val = { 60, 40, 100, 120 };
int capacity = 50;
double maxValue = getMaxValue(wt, val, capacity);
// Function call
System.out.println("Maximum value we can obtain = "
+ maxValue);
}
}
Python3
# Python3 program to solve fractional
# Knapsack Problem
class ItemValue:
"""Item Value DataClass"""
def __init__(self, wt, val, ind):
self.wt = wt
self.val = val
self.ind = ind
self.cost = val // wt
def __lt__(self, other):
return self.cost < other.cost
# Greedy Approach
class FractionalKnapSack:
"""Time Complexity O(n log n)"""
@staticmethod
def getMaxValue(wt, val, capacity):
"""function to get maximum value """
iVal = []
for i in range(len(wt)):
iVal.append(ItemValue(wt[i], val[i], i))
# sorting items by value
iVal.sort(reverse=True)
totalValue = 0
for i in iVal:
curWt = int(i.wt)
curVal = int(i.val)
if capacity - curWt >= 0:
capacity -= curWt
totalValue += curVal
else:
fraction = capacity / curWt
totalValue += curVal * fraction
capacity = int(capacity - (curWt * fraction))
break
return totalValue
# Driver Code
if __name__ == "__main__":
wt = [10, 40, 20, 30]
val = [60, 40, 100, 120]
capacity = 50
# Function call
maxValue = FractionalKnapSack.getMaxValue(wt, val, capacity)
print("Maximum value in Knapsack =", maxValue)
# This code is contributed by vibhu4agarwal
C#
// C# program to solve fractional Knapsack Problem
using System;
using System.Collections;
class GFG{
// Class for an item which stores weight and
// corresponding value of Item
class item
{
public int value;
public int weight;
public item(int value, int weight)
{
this.value = value;
this.weight = weight;
}
}
// Comparison function to sort Item according
// to val/weight ratio
class cprCompare : IComparer
{
public int Compare(Object x, Object y)
{
item item1 = (item)x;
item item2 = (item)y;
double cpr1 = (double)item1.value /
(double)item1.weight;
double cpr2 = (double)item2.value /
(double)item2.weight;
if (cpr1 < cpr2)
return 1;
return cpr1 > cpr2 ? -1 : 0;
}
}
// Main greedy function to solve problem
static double FracKnapSack(item[] items, int w)
{
// Sort items based on cost per units
cprCompare cmp = new cprCompare();
Array.Sort(items, cmp);
// Traverse items, if it can fit,
// take it all, else take fraction
double totalVal = 0f;
int currW = 0;
foreach (item i in items)
{
float remaining = w - currW;
// If the whole item can be
// taken, take it
if (i.weight <= remaining)
{
totalVal += (double)i.value;
currW += i.weight;
}
// dd fraction untill we run out of space
else
{
if (remaining == 0)
break;
double fraction = remaining / (double)i.weight;
totalVal += fraction * (double)i.value;
currW += (int)(fraction * (double)i.weight);
}
}
return totalVal;
}
// Driver code
static void Main(string[] args)
{
item[] arr = { new item(60, 10),
new item(100, 20),
new item(120, 30) };
Console.WriteLine("Maximum value we can obtain = " +
FracKnapSack(arr, 50));
}
}
// This code is contributed by Mohamed Adel
Maximum value we can obtain = 240