C++ 计算数据计划的最优价格
我对这个算法问题有疑问: 数据计划的成本为X。我们得到了一个数组(未排序) 整数,Y(1>n; 对于(int i=0;iC++ 计算数据计划的最优价格,c++,arrays,algorithm,C++,Arrays,Algorithm,我对这个算法问题有疑问: 数据计划的成本为X。我们得到了一个数组(未排序) 整数,Y(1>n; 对于(int i=0;i>e; a、 推回(e); } 排序(a.begin(),a.end()); lo=a[0],hi=a[n-1]; ans=LLONG_MAX; 而(lo获得反例的一个好方法如下。 考虑一些小数字的例子,如 1、2、3、4、5、6、7、8、9、10、< /代码>。 也许算法中X的最佳位置在序列右端附近(运行程序后的实际答案:84)。 现在将所有值大幅度增加,例如,获得10001
而(lo获得反例的一个好方法如下。 考虑一些小数字的例子,如<代码> 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)
这种二进制搜索方法首先需要证明如果X2>X1,那么H2
和如果X2>X1,那么L2>L1
,等等。@crowing Kitten是的。的确。我没有给出正式的证明,我对它的正确性有疑问,但我仍然编写了这个解决方案,因为我想不出更好的解决方案。我会尝试这样做k这是在数学社区(有点重新格式化,更多的例子,没有c++)。他们可能会把这归结为一个线性规划问题。交叉张贴:,。请。每个社区都应该有一个诚实的回答机会,而不会浪费任何人的时间。@CrouchingKitten,将来如果你要推荐另一个网站,请提醒人们不要交叉张贴:你可能会建议他们在之前删除这个问题把它贴在别处。谢谢!我已经设法得到了一个凸成本函数。但是由于有限差分f(x+1)-f(x)如果是非递减的,我们如何使用三元搜索?三元搜索只能在单峰函数上工作,对吗?@LanceHAOH:凸条件足以让三元搜索工作。也许比Wikipedia更清楚。@LanceHAOH还说,“我已经设法获得了凸成本函数”听起来很奇怪。你已经有了问题中唯一的代价函数,它已经给出了。你可能是说你得到了凸性的证明吗?我的错。在一些帮助下,我把代价函数写成了X中的二次函数。形式为f(X)=X^2+O(X)的函数是凸的,对吗?@LanceHAOH No,f(X)=x^2+1000x
对于偶数x和f(x)=x^2
对于奇数x肯定不是凸的。但是我们的特殊f(x)是凸的。只要看看点x,看看如果我们将x改变+-1,f(x)是如何变化的。有两种情况:(1)当x等于输入数组中的某个值时,(2)如果不是。或者更好,请遵循math.se中的公式来解决问题。
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
Elements: 1 2 2 2 3 4 5 6 7 9
Cost: 6 6 6 6 6 6 6 6 7 15
#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;
}