计算数据计划的最佳价格

Computing optimal price for data plan

本文关键字:最佳 数据 计划 计算      更新时间:2023-10-16

我对这个算法有问题:

数据计划的成本为X。我们得到了一个(未排序)的数组整数Y(1<=Y<=1e6)。对于每个整数Y,如果Y>X,则合计成本增加了X+(Y-X)*(Y-X)。否则,总成本为递增X。请找到X的值,以便总成本为最小化。

首先,O(N^2)方法很简单,易于编码,但对于大型输入数组(即2e5)来说,它的效率非常低。

我的方法是使用二进制搜索。作为前兆,我对数组进行排序。然后,我想象在条形图中根据数组中的整数画一条线——这条线将图表分为两部分:下半部分<= X中的每个元素和另一半> X中的元素。

设大于X的元素产生的成本为H,其余元素产生的费用为L。设BOT表示我的猜测的下界,TOP表示我的猜想的上界。

我的逻辑伪代码:

WHILE BOT <= TOP:
DO
X = (BOT+TOP)/2;
// Compute H and L based on X
// ...
ans = MIN(ans,H+L)
IF H == L:
BREAK;
ELSE IF H > L:
BOT = X + 1;
ELSE:
TOP = X - 1;
DONE
PRINT ANS

示例:

1 2 9 5 7 6 3 4 2 2

答案应该是70,因为我们可以选择6。

数组排序:

Elements: 1 2 2 2 3 4 5 6 7 9
Cost:     6 6 6 6 6 6 6 6 7 15

因此,6(8)+7+15=70

我的实际代码如下所示:

#include <iostream>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
using namespace std;
int n;
vector<int> a;
int hi,lo,mid,e;
long long ans,foo,bar;
long long scost(vector<int>::iterator up) {
long long s = 0;
vector<int>::iterator beg = a.begin();
while(beg != up) {
s += mid;
beg++;
}
return s;
}
long long ecost(vector<int>::iterator up) {
long long s = 0;
while(up != a.end()) {
s += (mid + (mid - *up) * (mid - *up));
up++;
}
return s;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
lo = INT_MAX;
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> e;
a.push_back(e);
}
sort(a.begin(),a.end());
lo = a[0], hi = a[n-1];
ans = LLONG_MAX;
while(lo <= hi) {
mid = (hi+lo)/2;
auto up = upper_bound(a.begin(),a.end(),mid);
foo = scost(up),bar = ecost(up);
ans = min(ans,foo+bar);
if(foo == bar) {
break;
} else if(foo < bar) {
lo = mid + 1;
} else {
hi = mid - 1;
}
}
cout << ans << "n";
return 0;
}

我用这个方法得到了错误的答案(它通过了示例测试用例)。尽管我觉得我的逻辑可能有缺陷,但我无法拿出任何反例。有人能告诉我一个更好的解决方案吗?

获取反例的好方法如下。考虑一些小数字的例子,比如1 2 3 4 5 6 7 8 9 10。使用您的算法,X的最佳位置可能在序列右端附近(运行程序后的实际答案:84)。现在,将所有值大量增加,例如,得到10001 10002 10003 10004 10005 10006 10007 10008 10009 10010。显然,现在与实际值相比,平方是无关紧要的,并且您的算法将声称X的最佳位置靠近序列的中心(运行程序后的实际答案:10085)。然而,应该清楚的是,如果第一个例子的解是X,那么第二个例子的解答是X + 10000

更一般地说,你的解决方案声称这两组的总和必须尽可能接近,但将其划分为这些确切的组是一种没有实际证据支持的说法。

为了实际解决这个问题,也许可以证明总成本函数f(x)是凸的,或者,换句话说,有限差分f(x+1)-f(x)是非递减的。如果这是真的,那么您可以使用三元搜索来找到解决方案,或者在有限差分f(x+1)-f(x)上使用二元搜索,而不是实际的f(x)