Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 计算数据计划的最优价格_C++_Arrays_Algorithm - Fatal编程技术网

C++ 计算数据计划的最优价格

C++ 计算数据计划的最优价格,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

我对这个算法问题有疑问:

数据计划的成本为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 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;
}