曲线
明明做作业的时候遇到了 n 个二次函数 Si(x)=a*x *x+b *x+c,他突发奇想设计了一个新的函数F(x)=max{Si(x)},i=1…n 。
明明现在想求这个函数在 [0,1000] 的最小值,要求精确到小数点后四位,四舍五入。
输入格式
输入包含 t 组数据,每组第一行一个整数 n;
接下来 n 行,每行 3个整数a ,b ,c ,用来表示每个二次函数的 3 个系数。注意:二次函数有可能退化成一次。
输出格式
每组数据输出一行,表示新函数F(x) 的在区间 [0,1000] 上的最小值。精确到小数点后四位,四舍五入。
样例输入:
2
1
2 0 0
2
2 0 0
2 -4 2
样例输出:
0.0000
0.5000
数据范围与提示:
对于50%的数据,1<=n<=100
对于100%的数据,1<=t<=10
1<=n<=10^5
0<=a<=100
0<=|b|<=5000
0<=|c|<=5000
这是一道很典型的三分问题,直接套用模板就可以写出
AC代码:
#include<stdio.h>
#include<algorithm>
using namespace std;
double a[100100],b[100100],c[100100];
int n,t;
double L,r,m1,m2;
double cal(double x)
{
int i;
double maxx=-0x7fffffff;
for(i=1; i<=n; i++)//F(x)=max{Si(x)}
maxx=max(maxx,a[i]*x*x+b[i]*x+c[i]);//
return maxx;
}
int main()
{
int i;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1; i<=n; i++)
scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
L=0,r=1000;//L和r代表的是范围!!!
//三分模板!!!
while(r-L>1e-11)
{
m1=L+(r-L)/3;
m2=r-(r-L)/3;
if(cal(m1)<=cal(m2))
r=m2;
else
L=m1;
}
//
printf("%.4lf\n",cal(L));//cal(L)或者cal(r)都可以,因为最后L和r无限接近,所以它的值是一样的
}
return 0;
}