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
", r, (int)floor(ans+0.5));
}
return 0;
}