曲线

https://loj.ac/problem/10013

题目描述

  定义\(F(x)=max(Si(x))\),给出\(n\)个二次函数\(S_i = ax^2 + bx + c\) ,求\(F(x)\)的最小值

思路

  由于\(S(x)\)要么是开口向上的二次函数,要么是单调增的一次函数,要么是常数,所以\(F(x)\)也一定是一个单调函数,并且不是很显然的能用三分求解(我也不是特别知道为什么),就主要讲一下如何用三分。我们现在有一个已知区间\([ L , R ]\),那么\(Lmid = L + ( R - L ) / 3,Rmid = R - ( R - L ) / 3\) 。我们以开口向上的二次函数为例,如果\(f(Lmid)< f(Rmid)\),那么我们可以证明\(Lmid\)和最优点在\(Rmid\)的同侧,即区间可以缩小至\([ L , Rmid ]\)。由此就可以进行三分。
\(\qquad\color{red}{三分的要求必须是严格的单调函数,如果存在一段f(Lmid)= f(Rmid),就无法进行三分了}\)

代码

#include <bits/stdc++.h>
using namespace std;
const int MAXN=101000;
double a[MAXN],b[MAXN],c[MAXN];
int n;
double f(double x)
{
    double maxx=-0x7fffffff;
    for(int i=1;i<=n;i++)
        maxx=max(maxx,a[i]*x*x+b[i]*x+c[i]);
    return maxx;
}
int main() 
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
        double eps=1e-10,l=0,r=1000;
        while(r>eps+l)
        {
            double lmid=l+(r-l)/3;
            double rmid=r-(r-l)/3;
            if(f(lmid)<=f(rmid))r=rmid;
            else l=lmid;
        }
        printf("%.4lf\n",f(r));
    }
    return 0;
}
posted @ 2019-10-29 17:34  fbz  阅读(163)  评论(0编辑  收藏  举报