码迷,mamicode.com
首页 > 其他好文 > 详细

P1883 函数

时间:2018-10-02 22:28:36      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:span   turn   font   ret   one   algo   判断   lse   space   

题目大意:

   给你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都过不了。

技术分享图片
  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 }
View Code

 

 

  

P1883 函数

标签:span   turn   font   ret   one   algo   判断   lse   space   

原文地址:https://www.cnblogs.com/LiqgNonqfu/p/9737820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!