标签: 解题报告 数学
原题见HDU 5954
高为2,底面圆直径为2的开口杯,平放时里面装有高为d的水。问倾斜到不能再倾斜时(水不能溢出),水的表面积为多少?
分析
水面有两种可能的形状:椭圆或椭圆的一部分。
其临界状况为:
此时椭圆经过杯底与杯口,得到被子恰好倾斜45°,空杯体积和水体积对称相等,故 d=1 。d>1 时为椭圆。(杯子倾斜画得累了,直接让水倾斜吧)
如图水面与杯底倾角为 β ,则dπ=12π⋅2tanβ+π(2−2tanβ)得
β=arctan(2−d)由投影关系得
Sans=πcosβd<1 时为椭圆截去一部分
建立坐标系如图,设水面倾角的余角为 θ ,则沿着水平面一层一层积分得到体积V=∫20S0dy每一层有相应的 x0,y0,α0,S0 满足关系式
⎧⎩⎨x0cosαS0=y0tanθ=x0−1=π−α+(x0−1)sinα
可见完全可以消去其它变量把 V 的式子展开
Vy0=1tanθ(cosα+1)=∫20S0dy=∫20π−α+cosαsinαdy=1tanθ∫α1π(π−α+cosαsinα)(−sinα)dα=1tanθ(πcosα−αcosα+sinα−13sin3α)|α1π
积分上下界的变化如图
y从0到2,α从π变化到α1 ,其中 α1=arccos(2tanθ−1) .
α1与θ 相互依赖,虽说有两个方程两个未知数可以解,但不如直接二分吧。
θ 的变化范围从0到 π4 ,且与体积正相关。二分其值寻找答案。求得对应的 α1,S1 ,由投影关系得
Sans=S1sinθ
代码
/*--------------------------------------------
* File Name: HDU 5954
* Author: Danliwoo
* Mail: Danliwoo@outlook.com
* Created Time: 2016-11-01 22:22:15
--------------------------------------------*/
#include <bits/stdc++.h>
using namespace std;
double Pi = acos(-1.0);
double eps = 1e-100;
double tran = 180/Pi;
double vd;
double V(double a) {
return Pi*cos(a) - a*cos(a) + sin(a) - pow(sin(a), 3)/3;
}
double get(double theta) {
double a1 = acos(2*tan(theta)-1);
double v = (V(a1) - V(Pi))/tan(theta);
return v;
}
bool eq(double x, double y) {
return fabs(x-y) < eps;
}
double find(double l, double r) {
int cnt = 200;
if(eq(get(l), vd)) return l;
while(cnt--) {
double mid = (l+r) / 2;
double gd = get(mid);
if(eq(gd, vd)) return mid;
if(gd > vd) r = mid;
else l = mid;
}
return l;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
double d;
scanf("%lf", &d);
vd = d * Pi;
if(eq(d, 0)) {
printf("0.00000\n");
continue;
}
if(d - 1 > 0) {
double theta = atan(2.0-d);
double ans = Pi/cos(theta);
// printf("d>1 theta = %.5f\n", theta*tran);
printf("%.5f\n", ans);
continue;
}
double theta = find(eps, Pi/4);
double a1 = acos(2 * tan(theta) - 1);
double S1 = Pi - a1 + cos(a1) * sin(a1);
double ans = S1 / sin(theta);
printf("%.5f\n", ans);
}
return 0;
}