【HIHOCODER 1142】 三分·三分求极值

描述


这一次我们就简单一点了,题目在此:
在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d。

输入


第1行:5个整数a,b,c,x,y。前三个数构成抛物线的参数,后两个数x,y表示P点坐标。-200≤a,b,c,x,y≤200

输出

第1行:1个实数d,保留3位小数(四舍五入)

样例输入

2 8 2 -2 6

样例输出

2.437

题解

抛物线和点之间的距离可以简单的用直线公式计算:
(d = min{sqrt((X - x)^2+(aX^2+bX+c-y)^2)})
直接看这个公式,完全不知道它是否为凸函数。
可以考虑选择抛物线极值点((-frac{b}{2a},frac{4ac-b^2}{4a}))
这个点将这个抛物线分成两个单调曲线,这两个曲线与某个固定点的距离函数是凸函数。
即用三分解决

#include <bits/stdc++.h>
#define ll long long
#define inf 1000000000
#define PI acos(-1)
#define bug puts("here")
#define REP(i,x,n) for(int i=x;i<=n;i++)
#define DEP(i,n,x) for(int i=n;i>=x;i--)
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const double eps=1e-6;
int a,b,c,x,y;
double check(double tx){
       double ty=a*tx*tx+b*tx+c;
       double t=(tx-x)*(tx-x)+(ty-y)*(ty-y);
       return sqrt(t);
}
int main(){
   // while(1)
    {
        a=read(),b=read(),c=read(),x=read(),y=read();
        double l=-200,r=-b/(2*a),ans;
        while(fabs(l-r)>eps){
            double h=(r-l)/3;
            if(check(l+h)<check(l+2*h)) r=l+2*h;
            else l=l+h;
        }
        ans=check(l);
        l=-b/(2*a),r=200;
        while(fabs(l-r)>eps){
            double h=(r-l)/3;
            if(check(l+h)<check(l+2*h)) r=l+2*h;
            else l=l+h;
        }
        ans=min(ans,check(l));
        printf("%.3f
",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zsyacm666666/p/7911559.html