hihocoder 第四十周 三分求极值

  题目链接:http://hihocoder.com/contest/hiho40/problem/1 ,一道简单的三分。

 


 

  题目是在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d。

用提示的算法:

  当函数是凸形函数时,二分法无法适用,这时就需要用到三分法。

  从三分法的名字中我们可以猜到,三分法是对于需要逼近的区间做三等分:

  

  我们发现lm这个点比rm要低,那么我们要找的最小点一定在[left,rm]之间。如果最低点在[rm,right]之间,就会出现在rm左右都有比他低的点,这显然是不可能的。 同理,当rm比lm低时,最低点一定在[lm,right]的区间内。利用这个性质,我们就可以在缩小区间的同时向目标点逼近,从而得到极值。

 

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define eps 1e-8
double a , b , c , X , Y;
inline double f(double x)
{
    return (X - x) * (X - x) + 
        (a * x * x + b * x + c - Y) * (a * x * x + b * x + c - Y);
}
double ternary_search(double l , double r)
{
    double lm = (2 * l + r) / 3;
    double rm = (l + 2 * r) / 3;
    while(r - l >= eps) {
        if(f(lm) < f(rm))
            r = rm;
        else
            l = lm;
        lm = (2 * l + r) / 3;
        rm = (l + 2 * r) / 3;
    }
    return lm;
}
int main()
{
    scanf("%lf %lf %lf %lf %lf" , &a , &b , &c , &X , &Y);
    if(f(X) <= eps) {
        printf("0.000\n");
    } else {
        double x = ternary_search(-500 , 500);
        printf("%.3lf\n" , sqrt(f(x)));
    }
    return 0;
}

 

posted on 2015-04-07 22:42  Vking不说话  阅读(166)  评论(0编辑  收藏  举报

导航