#10013. 「一本通 1.2 例 3」曲线(三分模板题)

曲线

明明做作业的时候遇到了 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;
}

猜你喜欢

转载自blog.csdn.net/zlzqq/article/details/109261430