基准时间限制:1 秒 空间限制:131072 KB 分值: 10
难度:2级算法题
B君要用一个表面积为S的圆锥将白山云包起来。
B君希望包住的白山云体积尽量大,B君想知道体积最大可以是多少。
注意圆锥的表面积包括底面和侧面。
Input
一行一个整数,表示表面积S。(1 <= S <= 10^9)
Output
一行一个实数,表示体积。
Input示例
8
Output示例
1.504506
wwwwodddd
(题目提供者)
思路:圆锥体积
V
与底面半径
r
成单调上凸关系(换句话说即函数
V=f(r)
的导函数为单调减并有零点)。那么我们可以采用三分来求
V
的极值。下图是三分的过程,其中
lowerBound、upperBound
是当前三分的上下界,而
mid1、mid2
则各为当前区间
[lowerBound,upperBound]
的
13
点以及
23
点。
val1、val2
各为
mid1、mid2
的对应值。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
//#define PI (3.1415926535897384626)
#define PI acos(-1.0)
#define EPS (1e-7)
using namespace std;
double S; //圆锥的表面积
double calc(double r) //已知圆锥底面半径r,计算当前圆锥的体积
{ double R=(S-PI*r*r)/PI/r; //侧面展开的扇形半径
double h=sqrt(R*R-r*r); //
return PI*r*r*h/3;
}
int main()
{
while(scanf("%lf",&S)!=EOF)
{
double lowerBound=0,
upperBound=sqrt(S/PI);
double mid1,mid2,val1,val2;
while(lowerBound+EPS<upperBound)
{
mid1=lowerBound+(upperBound-lowerBound)/3;
mid2=upperBound-(upperBound-lowerBound)/3;
val1=calc(mid1);
val2=calc(mid2);
if(val1<val2)
lowerBound=mid1;
else upperBound=mid2;
}
printf("%lf\n", val1);
}
return 0;
}