题目意思:
给你n(n<=10000)个抛物线,第i个抛物线的方程为fi(x) = ai*x*x + bi*x + c; (a>=0&&a<=100&&|b|<=5000,|c|<=5000)求x>=0&&x<=1000 内 F(x) = Max(fi(x)) 要最小.
解题思路:
首先对于每一条抛物线他们的ai>=0,所以所有的抛物线都是向上的,对于x∈[0,1000],求的是Max(fi(X)),所以我们可以将所有低于点( X,Max(fi(X) )的点都去掉,所以剩下的图形是一个凸性函数,所以我们可以根据三分法来求该凸性函数的最小值,即本题所要求的解.
原题地址:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=493&page=show_problem&problem=4222
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define MAXN 10010
#define eps 1e-12
typedef struct node {
double a,b,c;
void read(){
scanf("%lf%lf%lf",&a,&b,&c);
}
};
node F[MAXN];
int dcmp(double x){
if(fabs(x)<eps)
return 0;
return x<0?-1:1;
}
double max(double aa,double bb){
return dcmp(aa-bb)<0?bb:aa;
}
double f(int i,double x){
return F[i].a*x*x+F[i].b*x+F[i].c;
}
double Cal(double x,int n){
double MaxVal;
MaxVal = f(0,x);
for(int i=1;i<n;++i){
MaxVal = max(f(i,x),MaxVal);
}
return MaxVal;
}
double solve(int n){
double L,R,Mid,MMid,MidVal,MMidVal;
L = 0.00;
R = 1000.00;
while(dcmp(R-L)==1){
Mid = (R+L)/2;
MMid = (Mid+R)/2;
MidVal = Cal(Mid,n);
MMidVal = Cal(MMid,n);
if(dcmp(MidVal-MMidVal)==1){
L = Mid;
}
else R = MMid;
}
return Cal(L,n);
}
int main(){
int n;
int T,i;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(i=0;i<n;++i){
F[i].read();
}
double ans = solve(n);
printf("%.4lf\n",ans);
}
return 0;
}