Vijos - [一本通 1.2 例 3]曲线(三分)

题目链接https://vijos.org/d/ybttg/p/5c24bbe9f41362c9e1912767
时间限制:1000 ms 内存限制:512 MiB

题目描述

明明做作业的时候遇到了 n n 个二次函数 S i ( x ) = a x 2 + b x + c S_i(x)= ax^2 + bx + c ,他突发奇想设计了一个新的函数 F ( x ) = max { S i ( x ) } , i = 1 n F(x) = \max\{S_i(x)\}, i = 1\ldots n
在这里插入图片描述
明明现在想求这个函数在 [ 0 , 1000 ] [0,1000] 的最小值,要求精确到小数点后四位,四舍五入。

输入格式

输入包含 T T 组数据,每组第一行一个整数 n n

接下来 n n 行,每行 3 3 个整数 a a , b b , c c ,用来表示每个二次函数的 3 3 个系数。注意:二次函数有可能退化成一次。

输出格式

每组数据输出一行,表示新函数 F ( x ) F(x) 的在区间 [ 0 , 1000 ] [0,1000] 上的最小值。精确到小数点后四位,四舍五入。

样例数据

样例输入

2
1
2 0 0
2
2 0 0
2 -4 2

样例输出

0.0000
0.5000

限制与提示

对于 50 % 50\% 的数据, 1 n 100 1 \leq n \leq 100

对于 100 % 100\% 的数据, 1 T 10 , 1 n 1 0 5 , 0 a 100 , 0 b 5000 , 0 c 5000 1 \leq T \leq 10,1 \leq n \leq 10^5, 0 \leq a \leq 100, 0 \leq |b| \leq 5000, 0 \leq |c| \leq 5000

题解

题意:求这个函数 F ( x ) F(x) [ 0 , 1000 ] [0,1000] 的最小值。
思路:利用三分,首先把 l r l \sim r 这个区间分成三部分( m l ml m r mr )。接下来就是判断,我们因为要求最小值,所以我们要使得左边的值尽可能的小,这样最左边就是最小的。接下来就是找出 m l ml m r mr F ( x ) F(x) ,如果 m l ml F ( x ) F(x) 值小于 m r mr F ( x ) F(x) 值,那么就将 r r 向左边靠近,即 r = m r r = mr ,否则 l = m l l = ml

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
const int MAXN = 1e5 + 5;
struct ios_in {
    inline char gc() {
        static char buf[MAXN], *l, *r;
        return (l == r) && (r = (l = buf) + fread(buf, 1, MAXN, stdin), l == r) ? EOF : *l++;
    }
    template <typename _Tp>
    inline ios_in & operator >> (_Tp &x) {
        static char ch, sgn;
        for (sgn = 0, ch = gc(); !isdigit(ch); ch = gc()) {
            if (!~ch) return *this;
            sgn |= ch == '-';
        }
        for (x = 0; isdigit(ch); ch = gc())
            x = (x << 1) + (x << 3) + (ch ^ '0');
        sgn && (x = -x);
        return *this;
    }
}Cin;
int n, t;
int a[MAXN], b[MAXN], c[MAXN];
double Check(double x) {
    double max_ = -1 / eps;
    for (int i = 1; i <= n; i++)
        max_ = max(max_, a[i] * x * x + b[i] * x + c[i]);
    return max_;
}
int main() {
    Cin >> t;
    while (t--) {
        Cin >> n;
        for (int i = 1; i <= n; i++)
            Cin >> a[i] >> b[i] >> c[i];
        double l = 0, r = 1000;
        while (r - l > eps) {
            double ml = l + (r - l) / 3;
            double mr = r - (r - l) / 3;
            if (Check(ml) < Check(mr))
                r = mr;
            else l = ml;
        }
        printf("%.4lf\n", Check(l));
    }
    return 0;
}
发布了808 篇原创文章 · 获赞 331 · 访问量 244万+

猜你喜欢

转载自blog.csdn.net/lzyws739307453/article/details/101870225