📜  分数背包查询

📅  最后修改于: 2021-10-25 11:19:08             🧑  作者: Mango

给定一个整数数组,由正权重“W”和值“V”分别组成一对,以及一些由整数“C”组成的查询,指定背包的容量,找到可以放入的产品的最大值如果允许物品破损,则为背包。

例子:

建议您在阅读本文之前先阅读有关分数背包的这篇文章。

朴素的方法:一种简单的方法是按 V/W 值的降序对数组进行排序,即存在值/重量比。然后,对于每个查询,当背包未完全装满时,我们将迭代数组总结所需的整数值。
时间复杂度: O(q*n*log(n))

有效的方法:可以通过对排序数组的权重和值执行 prefix_sum 来优化查询。
下面是算法:

  1. 按值/权重比降序对数组进行排序。
  2. 分别查找数组的权重和值的前缀总和。
    • 用于回答查询:
    • 执行二分搜索以在 weight(W) 上找到 prefix_sum 大于 ‘C’ 的第一个元素。严格来说,在 ‘W’ 的 prefix_sum 数组中找到 ‘C’ 值的上限。假设此元素位于索引“X”处。
    • 包括来自索引 {0, X-1} 的值的总和以及来自索引“X”的可容纳在剩余容量中的小数值。

下面是上述方法的实现:

// C++ program to implement above approach
#include 
using namespace std;
  
// Function on the basis of which we will
// perform the sorting
bool comp(pair a, pair b)
{
    return (double)a.second / a.first >
                   (double)b.second / b.first;
}
  
// Function to sort the array on its value/weight
// and perform-sum on both weight and value
void preProcess(pair arr[], int n)
{
    sort(arr, arr + n, comp);
    for (int i = 1; i < n; i++) {
        arr[i].first += arr[i - 1].first;
        arr[i].second += arr[i - 1].second;
    }
}
  
// Function to answer queries
double maxValue(int w, pair arr[], int n)
{
    // If w is large enough
    // to cover all weights
    if (arr[n - 1].first <= w)
        return arr[n - 1].second;
  
    // Value to search on arr
    pair search_bound = { w, INT_MAX };
  
    // Index of the item which we will put
    // partially in our knap-sack
    int x = upper_bound(arr, arr + n, search_bound) - arr;
  
    // Required value
    if (x == 0)
        return (double)w * arr[0].second / arr[0].first;
    else
        return arr[x - 1].second +
              (double)(w - arr[x - 1].first) * 
              (arr[x].second - arr[x - 1].second) /
              (arr[x].first - arr[x - 1].first);
}
  
void PrintQueries(int query[], pair arr[],
                                        int n, int m)
{
    for (int i = 0; i < m; i += 1) {
        cout << maxValue(query[i], arr, n) << endl;
    }
}
  
// Driver code
int main()
{
    // Input array representing the data of w[] and v[]
    pair arr[] = { { 1, 2 }, { 1, 3 }, { 3, 7 } };
    int query[5] = { 1, 2, 3, 4, 5 };
  
    // Size of the array
    int n = sizeof(arr) / sizeof(pair);
    int m = sizeof(query) / sizeof(query[0]);
  
    // Pre-processing
    preProcess(arr, n);
  
    PrintQueries(query, arr, n, m);
  
    return 0;
}
输出:
3
5.33333
7.66667
10
12

时间复杂度: O((n+q)*log(n))

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。