第1部分 基礎算法(提高篇)--第2章 二分與三分1435:【例題3】曲線

1435:【例題3】曲線

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 982 通過數: 504
【題目描述】
明明做作業的時候遇到了n個二次函數Si(x)=ax2+bx+c,他突發奇想設計了一個新的函數F(x)=max(Si(x)), i=1,2…n。

明明現在想求這個函數在[0,1000]的最小值,要求精確到小數點後四位四捨五入。

【輸入】
輸入包含T 組數據 (T<10) ,每組第一行一個整數 n(n≤10000) ,之後n行,每行3個整數a(0≤a≤100),b(|b|≤5000),c(|c|≤5000) ,用來表示每個二次函數的3個係數,注意二次函數有可能退化成一次。

【輸出】
每組數據一個輸出,表示新函數F(x)的在區間[0,1000]上的最小值。精確到小數點後四位,四捨五入。

【輸入樣例】
2
1
2 0 0
2
2 0 0
2 -4 2
【輸出樣例】
0.0000
0.5000
【提示】
【數據範圍】

T<10,n≤10000,0≤a≤100,|b|≤5000,|c|≤5000;

前50%數據,n≤100。


思路:在這裏插入圖片描述
求區間[L,R],令m1 = l +( r-l)/3,m2=r-(r-l)/3接着計算函數值f(m1),f(m2)之後我們將兩點中函數值更優的那個點稱爲好點,差的那個點叫壞點。最優點會與好點與壞點同側。
f(m1)>f(m2),則m1是好點,m2是壞點。因此最優點會與m1在一起在m2的左側。即求區間[L,R]變成[L,m2].注意函數的嚴格單調性。
在這裏插入圖片描述
三分模板:
double l = 0,r = 1E9;
while(r - l >= 1e-3)//計算機中不存在真正的零值,所以用一個很小的值來代替零。
{
double m1 = l +( r-l)/3,m2 = r-(r-l)/3;
if(m1 < m2) l = m1;
else r = m2;
}
本題爲開口向上的二次函數,S的定義先單調遞減後單調遞增的的下凸函數。F(X)滿足單調性,選用三分法得出最小值。

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#define INF 0X3F3F3F3F
using namespace std;
int T,test,n;
double a[10005],b[10005],c[10005];
double x,maxx = 0,L,r,Lmid,rmid;
double cal(double x){
    int i,j;
    double maxx= -INF;
    for(i = 1;i <= n;i++) maxx=max(maxx,a[i]*x*x+b[i]*x+c[i]);
    return maxx;
} 
int main(){
    int i,j;
    cin>>T;
    for(test = 1;test <= T;test++){
        cin>>n;
        for(i = 1;i <= n;i++) cin>>a[i]>>b[i]>>c[i];
        L = 0;r = 1000;
        while(L+1e-11 < r){
            Lmid = L + (r-L)/3;
            rmid = r - (r-L)/3;
            if(cal(Lmid) <= cal(rmid)) r = rmid;
            else L = Lmid;
        }
        printf("%.4lf\n",cal(L));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章