给定一个整数数组,由正权重“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 值的降序对数组进行排序,即存在值/重量比。然后,对于每个查询,当背包未完全装满时,我们将迭代数组总结所需的整数值。
时间复杂度: 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))
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。