题目大意:
给你n个二次或一次的函数f1(x),f2(x)...fn(x),构造F(x)=min(f1(x),...,fn(x)),现在求F(x)在[0,1000]的最小值。(T < 10, n ≤ 10000)保留4位小数。
思路:
感觉是二分。一般情况下,F应该是下凸的,所以二分时保证两端点的导数一正一负就好。
关键是特殊情况。。。。。。。。。。F有可能单调:
1.只有一个一次函数bx+c;b小于0时,单减;b大于0时,,单增;
2.只有一个二次函数,对称轴在[0,1000]外;
3.多个函数但最终也单调,只需在二分前判断一下r和l的符号是否一致。
更重要的:注意精度!注意精度!注意精度!r-l<=1e-10,-9都过不了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 6 using namespace std; 7 8 int func[10004][3],T,n; 9 double ans=0; 10 11 12 13 double qiuzhi(int xuhao,double yuan) 14 { 15 double ret,a=func[xuhao][0],b=func[xuhao][1],c=func[xuhao][2]; 16 ret=yuan*yuan*a+b*yuan+c; 17 return ret; 18 } 19 20 double qiudao(int xuhao,double yuan) 21 { 22 double ret,a=func[xuhao][0],b=func[xuhao][1]; 23 ret=2*a*yuan+b; 24 return ret; 25 } 26 27 int work(double x) 28 { 29 int ret=1; 30 double zui=qiuzhi(1,x); 31 for(int i=2;i<=n;i++) 32 { 33 if(zui<qiuzhi(i,x)) 34 { 35 zui=qiuzhi(i,x); 36 ret=i; 37 } 38 } 39 return ret; 40 } 41 42 int main() 43 { 44 scanf("%d",&T); 45 for(int I=1;I<=T;I++) 46 { 47 scanf("%d",&n); 48 ans=0; 49 for(int i=1;i<=n;i++) 50 { 51 scanf("%d%d%d",&func[i][0],&func[i][1],&func[i][2]); 52 } 53 if(n==1) 54 { 55 if(func[1][0]==0) 56 { 57 if(func[1][1]>=0)printf("%d.0000\n",func[1][2]); 58 else 59 { 60 double tt=qiuzhi(1,1000); 61 printf("%.4lf\n",tt); 62 } 63 } 64 else 65 { 66 ans=(-func[1][1]); 67 ans=ans/(2*func[1][0]); 68 if(ans>=0&&ans<=100) 69 { 70 ans=(4*func[1][0]*func[1][2]-func[1][1]*func[1][1]); 71 ans=ans/(4*func[1][0]); 72 } 73 else 74 { 75 ans=min(qiuzhi(1,0),qiuzhi(1,1000)); 76 } 77 printf("%.4lf\n",ans); 78 } 79 continue; 80 } 81 double l=0; 82 double r=1000; 83 int x1=work(l); 84 int x2=work(r); 85 if(qiudao(x1,0)>0&&qiudao(x2,1000)>0) 86 { 87 ans=qiuzhi(x1,0); 88 printf("%.4lf\n",ans); 89 continue; 90 } 91 if(qiudao(x1,0)<0&&qiudao(x2,1000)<0) 92 { 93 ans=qiuzhi(x2,1000); 94 printf("%.4lf\n",ans); 95 continue; 96 } 97 while(r-l>1e-10) 98 { 99 double mid=(l+r)/2; 100 int x; 101 x=work(mid); 102 double dao=qiudao(x,mid); 103 if(dao>0) 104 { 105 r=mid; 106 } 107 else 108 { 109 l=mid; 110 } 111 } 112 ans=l; 113 int x=work(ans); 114 ans=qiuzhi(x,ans); 115 printf("%.4lf\n",ans); 116 } 117 return 0; 118 }