HDU4355(三分)

来源:互联网 发布:高中物理仿真实验软件 编辑:程序博客网 时间:2024/06/05 08:56

题目大意:

有n个精灵在一维坐标轴上,并且每个精灵都有一个权值,每个精灵从一个点到达一个点要花费:S3*W(s代表距离),问所有的精灵要聚在一起,最小花费是多少。
设最终要求的点的位置是x,则花费为:∑fabs(x[i]-x)^3*w[i]。此函数为凸函数,因此可以三分。

三分基本套路:

       通过对一段区域中间分一点,将区域分为左右两部分,再分别取中间,对两个中间值较优的保留,更新边界。

使边界 r-l<=1e-9 ;然后从左右取个较优解。




#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int inf=0x3f3f3f3f;int num;double dis[50001];double m[50001];int change(double d){    int r;    if(d-(int)d>=0.5)        r=(int)d+1;    else        r=(int)d;    return r;}double ABS(double n){    return n>0?n:-n;}double res(double d){    double unha=0;    for(int i=1;i<=num;++i)    {        double mile=ABS(d-dis[i]);        unha+=mile*mile*mile*m[i];    }    return unha;}int main(){   int n,kase=0;   scanf("%d",&n);   while(n--)   {       scanf("%d",&num);       double minn=inf,maxx=-inf;       for(int i=1;i<=num;++i)       {           scanf("%lf%lf",&dis[i],&m[i]);           if(dis[i]<minn)            minn=dis[i];           if(dis[i]>maxx)            maxx=dis[i];       }       cout<<"Case #"<<++kase<<": ";       double l=minn,r=maxx;       double mid=(l+r)/2;       double lun,run;       double lmid=(l+mid)/2;       double rmid=(r+mid)/2;       lun=res(lmid);       run=res(rmid);       while(r-l>1e-9)       {           if(lun<run)           {              r=mid;              mid=(l+r)/2;              lmid=(l+mid)/2;              rmid=(r+mid)/2;           }           else           {              l=mid;              mid=(l+r)/2;              lmid=(l+mid)/2;              rmid=(r+mid)/2;           }       lun=res(lmid);       run=res(rmid);       }       double ans1=res(l);       double ans2=res(r);       printf("%d\n",change(ans1<ans2?ans1:ans2));   }    return 0;}















0 0
原创粉丝点击