hdoj 3714 Error Curves (三分)

http://acm.hdu.edu.cn/showproblem.php?pid=3714
题目大意:给你 n n 个二次函数Si(x),作函数 F(x)=max(Si(x)) F ( x ) = m a x ( S i ( x ) ) ,求 F(x) F ( x ) [0,1000] [ 0 , 1000 ] 上的最小值。

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

那么这题的方法就很明了了,但有一点要注意,精度要到 109 10 − 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值