给定一个整数数组,该数组由正权重“ W”组成,值“ V”分别成对存在,而某些查询由一个整数“ C”组成,指定背包的容量,求出可以放入的产品的最大值如果允许物品破损,则采用背包。
例子:
Input: arr[] = { {1, 2}, {1, 3}, {3, 7} }, q = {1, 2, 3, 4, 5}
Output: {3, 5.33333, 7.66667, 10, 12}
For ‘C’ = 1, we will fill the knap-sack with element of value 3.
For ‘C’ = 2, first, we fill with element of value 3, then remaining 1 capacity
with element with value 7.
For ‘C’ = 3, first we fill with element of value 3, then remaining 2 capacities
with element with value 7.
For ‘C’ = 4, first we fill with element of value 3, then remaining 3 capacities
with element with value 7.
For ‘C’ = 5, first we fill with element of value 3, next 3 capacities
with element with value 7 and remaining 1 with element of value 1.
建议您先阅读有关分数背包的这篇文章,然后再阅读本文。
天真的方法:一种简单的方法是按照V / W值的降序对数组进行排序,即存在值/权重比。然后,对于每个查询,我们将在knap-sack尚未完全满的情况下对数组求和,对所需的整数值进行迭代。
时间复杂度: O(q * n * log(n))
高效的方法:可以通过对权重和值执行排序数组的prefix_sum来优化查询。
下面是算法:
- 按值/重量比降序对数组进行排序。
- 分别找到数组的“权重”和“值”的前缀和。
-
- 对于回答查询:
- 执行二进制搜索以找到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))