1. 程式人生 > >P1883 函數

P1883 函數

cstring print int bdc using close names work ont

題目大意:

給你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 函數