目录
前言
分数背包问题:
在分数背包问题中,物品可以被分割成更小的部分,可以部分装入背包,而不是只能选择整个物品装入或不装入背包。
一、贪心策略
贪心法在解决分数背包问题时,可以按照 单位重量价值(价值/重量)从大到小的顺序,依次将单位重量价值最大的物品放入背包,直到背包装满为止。这样能够得到一个最优解。
二、具体步骤
- 计算每个物品的单位重量价值(value/weight)类似于 性价比的意思(不是屌丝饮料哦~)。
- 按照单位重量价值从大到小排序。
- 依次将单位重量价值最大的物品放入背包,直到背包无法再放入为止。
实例如下:
这里按照性价比排序:2.1 、2 、1.5 、1.2 、1
总重量=30+10+20+40=100(这里最后一样物品取4/5)
总价值=65+20+30+48=163
三、代码实现
伪代码:
FractionalKnapsack(values[], weights[], capacity):
n = length of values[] and weights[]
// 计算每个物品的单位重量价值
for i from 0 to n-1:
value_per_weight[i] = values[i] / weights[i]
// 按单位重量价值从大到小排序
sort items by value_per_weight in descending order
total_value = 0
remaining_capacity = capacity
// 尝试将物品放入背包
for i from 0 to n-1:
if weights[i] <= remaining_capacity:
total_value = total_value + values[i]
remaining_capacity = remaining_capacity - weights[i]
else:
total_value = total_value + value_per_weight[i] * remaining_capacity
break
return total_value
C++代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Item {
int value;
int weight;
double value_per_weight;
};
bool compare(Item a, Item b) {
return a.value_per_weight > b.value_per_weight;
}
double fractional_knapsack(vector<int> value, vector<int> weight, int capacity) {
vector<Item> items;
for (int i = 0; i < value.size(); i++) {
items.push_back({value[i], weight[i], (double)value[i]/weight[i]});
}
sort(items.begin(), items.end(), compare);
double total_value = 0.0;
int remaining_capacity = capacity;
for (int i = 0; i < items.size(); i++) {
if (remaining_capacity >= items[i].weight) {
total_value += items[i].value;
remaining_capacity -= items[i].weight;
} else {
total_value += items[i].value_per_weight * remaining_capacity;
break;
}
}
return total_value;
}
int main() {
vector<int> value = {60, 100, 120};
vector<int> weight = {10, 20, 30};
int capacity = 50;
cout << fractional_knapsack(value, weight, capacity) << endl; // 输出为240.0
return 0;
}
结果:(这里我写的性价比分别是 60,50,40 可以根据要求自我修改)
总结:
贪心算法在解决背包问题时具有以下优点和缺点:
优点:
1. 算法简单易懂:贪心算法通常实现简单,易于理解和实现。
2. 时间复杂度低:贪心算法通常具有较低的时间复杂度,适用于大部分实际问题的求解。
3. 快速得到一个近似解:贪心算法能够在较短时间内得到一个较好的近似解,对于一些实际问题来说已经可以满足要求。
缺点:
1. 不能保证得到最优解:贪心算法的局部最优策略不一定能够达到全局最优解,因此无法保证对所有问题都能够得到最优解。
2. 可能存在局部最优解误判:贪心算法可能会因为贪心选择而导致达到一个局部最优解,但最终并不是整体最优解。
3. 需要正确的贪心选择策略:贪心算法对于不同的问题需要选择合适的贪心策略,否则可能会得到错误的结果。
综上所述,贪心算法在背包问题中有其优势和局限性,具体是否选择使用贪心算法取决于问题本身的特点和要求。在实际应用中,需要仔细考虑问题的具体情况,综合考虑算法的优势和局限性,选择合适的解决方法。