1. 程式人生 > >poj3737UmBasketella三分法求極值

poj3737UmBasketella三分法求極值

題目地址

題目大意:給定一個圓錐體的表面積s,求這個圓錐體的最大體積以及圓錐體體積最大時的底面半徑和高。

題目分析:題意十分簡單明瞭。根據圓錐體表面積公式:π * r * r + π * r * l = s(r是底面半徑,l是母線長),l = sqrt(h* h + r * r),帶入表面積方程可得圓錐高h = sqrt((s/π/r - r)^2 - r * r),根據此式可得一不等式:s/π/r >2r。由此得出底面半徑上界為sqrt(s/2π).繼續整理方程可得圓錐體體積v = π*sqrt(s^2*r^2/π/π - 2sr^4/π)/3。可以很清楚的看出,圓錐體的體積v是關於圓錐體底面半徑的一個2次方程,開口向下,是個凸形圖形求極值的問題,很容易想到三分底面半徑r。

詳情請見程式碼:

  1. #include <iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. usingnamespace std;  
  5. #define eps 1e-8
  6. #define PI acos(-1.0)
  7. double s,h,r,v;  
  8. double geth(double ra)//求當圓錐底面半徑為ra時的高
  9. {  
  10.     double hi;  
  11.     hi = (s/PI/ra - ra) * (s/PI/ra - ra);  
  12.     hi -= (ra * ra);  
  13.     if(hi < 0)  
  14.         return -1;  
  15.     hi = sqrt(hi);  
  16.     return hi;  
  17. }  
  18. int main()  
  19. {  
  20.     while(scanf("%lf",&s) != EOF)  
  21.     {  
  22.         double l,r,midl,midr,v1,v2;  
  23.         l = 0;  
  24.         r = sqrt(s / PI / 2);  
  25.         while(r - l > eps)  
  26.         {  
  27.             midl = (l + r) / 2;  
  28.             midr = (r + midl) / 2;  
  29.             v1 = geth(midl);  
  30.             v2 = geth(midr);  
  31.             v1 = PI * midl * midl * v1 / 3;  
  32.             v2 = PI * midr * midr * v2 / 3;  
  33.             if(v1 > v2)  
  34.                 r = midr;  
  35.             else
  36.                 l = midl;  
  37.         }  
  38.         printf("%.2lf\n%.2lf\n%.2lf\n",v1,geth(midl),midl);  
  39.     }  
  40.     return 0;  
  41. }