HDU 4355 Party All the Time 三分算法

HDU 4355 Party All the Time 三分算法

题意

给你N个人的位置x和相应重量w,他们要到达同一个位置p,他们每个人的花费的精力等于\(|s[i]-p|^{3}*w\),然后我们需要求一个位置,使得所有人的花费之和最小。

解题思路

根据上面的公式,我们可以知道这个函数不是一个简单的单调函数,最起码是个凹函数(这里需要一个数学上的知识),对于一般情况我们会使用二分法来进行处理,但是这里不是单调函数了,而是一个凹函数,这样我们就不能用二分了,新的算法应运而生——三分算法。

三分算法基本上和二分很相似,就相差了很少的一部分。这里不再讲解,直接推荐相关博客就行了。

三分算法讲解博客推荐
https://blog.csdn.net/huzujun/article/details/81187455

代码实现

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const double esp=1e-6;
const int inf=0x3f3f3f3f;
const int MAXN=5E4+7;
struct nod{
    double x, w;
}node[MAXN];
int t, n; 
double solve(double x)
{
    double sum=0;
    for(int i=0; i<n; i++)
    {
        sum+=pow(abs(x - node[i].x), 3.0) * node[i].w; 
    }
    return sum;
}
int main()
{
    scanf("%d", &t);
    for(int r=1; r<=t; r++)
    {
        scanf("%d", &n);
        double left=1e7, right=-1e6-7;
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf", &node[i].x, &node[i].w);
            left=min(left, node[i].x);
            right=max(right, node[i].x);
        }
        double ans, mid, midr;
        while(right-left>=esp)
        {
            mid=(left+right)/2;
            midr=(mid+right)/2;
            if(solve(mid) > solve(midr))
                left = mid;
            else right = midr;
        }
        ans=solve(left);
        printf("Case #%d: %d\n", r, (int)floor(ans+0.5));
    }
    return 0;
}

相关推荐