【题目描述】
明明做作业的时候遇到了n个二次函数Si(x)= ax2 + bx + c,他突发奇想设计了一个新的函数F(x) = max(Si(x)), i = 1...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
【分析】
因为本题模型是一个凸函数而不一定有单调性,所以要三分答案。
关于三分:http://blog.youkuaiyun.com/wzy_1988/article/details/9075963
【代码】
#include<iostream>
#include<cstdio>
using namespace std;
double ji=1e-9;
int n,a[10010],b[10010],c[10010];
void init()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]);
return;
}
double fi(double x)
{
double re=a[1]*x*x+b[1]*x+c[1];
for (int i=2;i<=n;i++)
re=max(re,(double)a[i]*x*x+b[i]*x+c[i]);
return re;
}
void work()
{
double l=0,r=1000;
double lm,rm;
while (r-l>ji)
{
lm=l+(r-l)/3.0;
rm=r-(r-l)/3.0;
if (fi(lm)>fi(rm)) l=lm;
else r=rm;
}
printf("%.4lf\n",fi(l));
return;
}
int main()
{
freopen("curves.in","r",stdin);
freopen("curves.out","w",stdout);
int t;
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
init();
work();
}
return 0;
}