三分求最小值——HDU 2241

来源:互联网 发布:视频转换器 for mac 编辑:程序博客网 时间:2024/05/20 20:02

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2241


中文题目,不解释


解题思路:

对于每个折线区间,Y+F之和必然是一个凹函数,求导就知道。

对于每段折线进行三分求极值,然后取所有段极值的最小值,即可得到最后解。


源代码:

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<set>#include<map>#include<vector>#include<algorithm>#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;const double eps=1e-6;LL N;int M;struct node{    double x,y;}p[10005];double f(double x){    return N/x/x;}double cal(int key)   //在区间k中通过三分求取最小影响{    double k,b;       //y函数的系数    double lx,ly,rx,ry;    double ll,rr;    double x;    lx=p[key].x;    ly=p[key].y;    rx=p[key+1].x;  ry=p[key+1].y;    k=(ry-ly)/(rx-lx);    b=ly-k*lx;    while(rx-lx>eps)    {        ll=lx+(rx-lx)*0.382;        rr=lx+(rx-lx)*0.618;        if(f(ll)+k*ll>f(rr)+k*rr)            lx=ll;        else            rx=rr;    }    return min(f(lx)+lx*k,f(rx)+rx*k)+b;}int main(){freopen("in.txt","r",stdin);int i;int l,r,ll,rr;double ans;while(scanf("%d%I64d",&M,&N)==2){    memset(p,0,sizeof(p));    for(i=1;i<=M;i++)    {        scanf("%lf%lf",&p[i].x,&p[i].y);    }    if(N==0)    //这个特判一定是不能少的    {        printf("0.000\n");        continue;    }        ans=INF;    for(i=1;i<M;i++)    //枚举区间    {        ans=min(ans,cal(i));    }    printf("%.3lf\n",ans+eps);    continue;}return 0;}

原创粉丝点击