分数背包

进阶

分数背包因物品可分,贪心策略天然有效。

分数背包

输入偶数个整数:重量、价值交替。背包容量 50。

AlgoAnim · 分数背包

待机

速度
待机
// 源代码
1double fractionalKnapsack(int W, vector<int>& wt, vector<int>& val) {
2    int n = wt.size();
3    vector<int> idx(n);
4    iota(idx.begin(), idx.end(), 0);
5    sort(idx.begin(), idx.end(), [&](int a, int b) {
6        return (double)val[a] / wt[a] > (double)val[b] / wt[b];
7    });
8    double total = 0;
9    int remain = W;
10    for (int i : idx) {
11        int take = min(wt[i], remain);
12        total += (double)val[i] * take / wt[i];
13        remain -= take;
14        if (remain == 0) break;
15    }
16    return total;
17}

复杂度分析

时间 O(n log n)
空间 O(n)
最优 O(n) 已排序时
最坏 O(n log n)

算法讲解

分数背包问题允许把物品切成任意比例装入背包,因此"先装性价比最高的"就是最优策略。

按单位价值(价值/重量)从大到小排序后,依次尽量装满,直到背包容积用完。

和 0-1 背包的区别在于:0-1 背包不能分割物品,所以贪心不保证最优;而分数背包可分,贪心恰好正确。

这正好帮助理解"贪心正确性依赖于问题是否具有贪心选择性质"。