2018NOIP模拟题 曲线

题目描述

       小 Y 同学的弟弟小 Z 昨天学习了数学中的一元二次函数,但是由于学业不精,他一个晚上都在缠着小 Y 问一元二次函数的极值问题,小 Y 烦不可耐,于是,想请你帮忙弄个程序来应付小 Z 。程序要完成以下任务:给你 N 个二次函数,记第i个为:fi(x)=aix2+bix+ci。(0ai100bi5000ci5000),设函数F(x)=max{f1(x),f2(x)fn(x)}

请你求出F(x) 的在区间[0,1000] 上的最小值,结果保留 3 位小数。

输入输出格式

输入格式

第一行是一个整数 N
接下来 N行,每行 3个实数ai,bi,ci,之间有一个空格分隔。

输出格式

输出一行一个实数,表示 F(x) 的在区间[0,1000] 上的最小值。

输入样例

#1
1
2 -4 2

#2
2
3 -2 1
2 -4 2

输出样例

#1
0.000

#2
0.686

数据范围

70% 的数据:1N1000;
100% 的数据:1N100000。
 

题解 

赤裸裸的板子题。

因为答案区间并不是单调的(如果是单调的那么就可以二分),所以考虑三分。

三分也不难,况且是板子题,洛谷3382就是模板。

三分就是考虑在(r-l)/3+l和2*(r-l)/3处进行范围缩小

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>

using namespace std;

const double esp=1e-10;
const int N=105000;

int n;
double ans;

struct Node
{
    double a;
    double b;
    double c;
} k[N];

void init()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        cin>>k[i].a>>k[i].b>>k[i].c;
    return;
}

bool check(double l1,double l2)
{
    double t1=-1e100,t2=-1e100;
    for(int i=1; i<=n; i++)
    {
        t1=max(t1,k[i].a*l1*l1+k[i].b*l1+k[i].c),
        t2=max(t2,k[i].a*l2*l2+k[i].b*l2+k[i].c);
    }
    ans=t1;
    return t1>t2;
}

void work()
{
    double l=0.0,r=1000.0;
    while(l+esp<r)
    {
        double mid1=(r-l)/3.000+l,mid2=2.0*(r-l)/3.000+l;
        if(check(mid1,mid2))l=mid1;
        else r=mid2;
    }
    printf("%.3lf
",ans);
}

int main()
{
    init();
    work();
    return 0;
}
 

出处:https://www.cnblogs.com/yujustin/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
温馨提示:尽量使用版本较高的浏览器,并打开极速模式。
原文地址:https://www.cnblogs.com/yujustin/p/11133639.html