第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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章