标签:
题目链接:HDU 4355
题面:
1 4 0.6 5 3.9 10 5.1 7 8.4 10
Case #1: 832
题意:
给定一维上若干点xi,每个点有对应的权值wi,求一个点的位置p,使得sigma fabs(p-xi)^3*wi最小。
解题:
看了网上现有的所有博客,都是直接说是个凸函数,三分一下就好。求导好像也不直观,也不知道具体是怎么证明的,姑且认为是个开口向上的二次函数(因为求的是最小值,且直观上,p的位置肯定是在中间好),那么三分就可以求解了,需要注意的是,这题C++应该是会T的,交G++才能过,然后向最近位取舍,应该用%.0lf输出。
【三分性质】
将区间三等分,取左等分点为lmid,右等分点为rmid,比如此题,二次函数开口向上,那么就算lmid的函数值为lv,rmid的函数值为rmid,比较lv和rv的值,假设最小值不在lmid和rmid之间,在两侧,那么lv,rv哪个更小,其对应的等分点就更接近最值,故而舍弃大的那边。倘若,最小值在lmid和rmid之间,那么无论舍弃哪一边,都不会丢弃最值,同时达到逼近最值的效果,因为最值在何处,我们是不知道的,故而和第一种情况相统一,舍弃较大的一边。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#define LL long long
#define eps 1e-8
using namespace std;
double x[50010],w[50010];
int n;
double cal(double y)
{
double tmp,res=0.0;
for(int i=0;i<n;i++)
{
tmp=fabs(y-x[i]);
res+=tmp*tmp*tmp*w[i];
}
return res;
}
int main()
{
int t,p;
scanf("%d",&t);
LL ans;
for(int i=1;i<=t;i++)
{
scanf("%d",&n);
for(int j=0;j<n;j++)
scanf("%lf%lf",&x[j],&w[j]);
double le=-1e6,ri=1e6;
while(ri-le>eps)
{
double lmid,rmid,lv,rv;
lmid=(ri-le)/3+le;
rmid=ri-(ri-le)/3;
lv=cal(lmid);
rv=cal(rmid);
if(lv>rv)
le=lmid;
else
ri=rmid;
}
printf("Case #%d: %.0lf\n",i,cal(le));
}
return 0;
}HDU 4355 Party All the Time(三分)
标签:
原文地址:http://blog.csdn.net/david_jett/article/details/52078267