HDU 4355 Party All the Time(三分)
扫描二维码
随时随地手机看文章
题目链接:HDU 4355
题面:
Party All the Time Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5266 Accepted Submission(s): 1625
Problem Description In the Dark forest, there is a Fairy kingdom where all the spirits will go together and Celebrate the harvest every year. But there is one thing you may not know that they hate walking so much that they would prefer to stay at home if they need to walk a long way.According to our observation,a spirit weighing W will increase its unhappyness for S3*W units if it walks a distance of S kilometers.
Now give you every spirit's weight and location,find the best place to celebrate the harvest which make the sum of unhappyness of every spirit the least.
Input The first line of the input is the number T(T<=20), which is the number of cases followed. The first line of each case consists of one integer N(1<=N<=50000), indicating the number of spirits. Then comes N lines in the order that x[i]<=x[i+1] for all i(1<=i
Output For each test case, please output a line which is "Case #X: Y", X means the number of the test case and Y means the minimum sum of unhappyness which is rounded to the nearest integer.
Sample Input 1 4 0.6 5 3.9 10 5.1 7 8.4 10
Sample Output Case #1: 832
Author Enterpaise@UESTC_Goldfinger
Source 2012 Multi-University Training Contest 6
题意:
给定一维上若干点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
#include
#include
#include
#include
#include
#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;ieps)
{
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: %.0lfn",i,cal(le));
}
return 0;
}