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

題目鏈接https://vijos.org/d/ybttg/p/5c24bbe9f41362c9e1912767
時間限制:1000 ms 內存限制:512 MiB

題目描述

明明做作業的時候遇到了nn個二次函數Si(x)=ax2+bx+cS_i(x)= ax^2 + bx + c,他突發奇想設計了一個新的函數F(x)=max{Si(x)},i=1nF(x) = \max\{S_i(x)\}, i = 1\ldots n
在這裏插入圖片描述
明明現在想求這個函數在[0,1000][0,1000]的最小值,要求精確到小數點後四位,四捨五入。

輸入格式

輸入包含TT組數據,每組第一行一個整數nn

接下來nn行,每行33個整數aa,bb,cc,用來表示每個二次函數的33個係數。注意:二次函數有可能退化成一次。

輸出格式

每組數據輸出一行,表示新函數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\%的數據,1n1001 \leq n \leq 100

對於100%100\%的數據,1T10,1n105,0a100,0b5000,0c50001 \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]的最小值。
思路:利用三分,首先把lrl \sim r這個區間分成三部分(mlmlmrmr)。接下來就是判斷,我們因爲要求最小值,所以我們要使得左邊的值儘可能的小,這樣最左邊就是最小的。接下來就是找出mlmlmrmrF(x)F(x),如果mlmlF(x)F(x)值小於mrmrF(x)F(x)值,那麼就將rr向左邊靠近,即r=mrr = mr,否則l=mll = 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章