hdoj 3714 Error Curves

http://acm.hdu.edu.cn/showproblem.php?pid=3714
题目大意:给你n个二次函数Si(x),作函数F(x) = max(Si(x)),求F(x)在[0,1000]上的最小值。
最大值最小值问题可以想到二分,但这个函数貌似不是单调的,而是先减后增的,因为给定的是n个二次函数,又给定了区间,所以要么单减要么单增要么增减要么减增的,所以最大值连起来是个单峰函数,所以可以用三分。
三分就是为对付非单调函数但是单峰函数的,不是将区间二等分而是三等分,每次取一个lm,一个rm,lm = l + (r - l) / 3; rm = r - (r - l) / 3; 然后搜索方式与二分类似,对于求极小值的情况,若lm比rm低(即lm对应的函数值 < rm函数值)则极小点肯定在[ l, rm ] ,反之在[ lm, r ]。
https://blog.csdn.net/u012469987/article/details/50897291
这是大神写的二分三分法的详解,可以参考。

那么这题的方法就很明了了,但有一点要注意,精度要到1e-9才够。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int T,n;
double a[10010],b[10010],c[10010];
int main()
{
    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 lm,rm,l=0,r=1000;
        while(r-l>1e-9)
        {
            double max1=-5000000000,max2=-5000000000;
            lm=l+(r-l)/3.0;
            rm=r-(r-l)/3.0;
            for(int i=1;i<=n;i++)
            {
                max1=max(a[i]*lm*lm+b[i]*lm+c[i],max1);
                max2=max(a[i]*rm*rm+b[i]*rm+c[i],max2);
            }
            if(max1<max2)
            {
                r=rm;
            }
            else
            {
                l=lm;
            }
        }
        double max1=-5000000000;
        for(int i=1;i<=n;i++)
        {
            max1=max(a[i]*lm*lm+b[i]*lm+c[i],max1);
        }
        printf("%.4lf\n",max1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sdxtcqs/article/details/79659238