HDU 5954 - Do not pour out - [積分+二分][2016ACM/ICPC亞洲區瀋陽站 Problem G]

題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=5954php

Problem Description
You have got a cylindrical cup. Its bottom diameter is 2 units and its height is 2 units as well.
The height of liquid level in the cup is d (0 ≤ d ≤ 2). When you incline the cup to the maximal angle such that the liquid inside has not been poured out, what is the area of the surface of the liquid?
c++

Input
The first line is the number of test cases. For each test case, a line contains a float-point number d.
ide

Output
For each test case, output a line containing the area of the surface rounded to 5 decimal places.
ui

Sample Input
4
0
1
2
0.424413182
spa

Sample Output
0.00000
4.44288
3.14159
3.51241.net

 

題意:code

有一個圓柱形杯子,底部直徑爲 $2$,高爲 $2$,告訴你當杯子水平放置時水面高度爲 $d(0 \le d \le 2)$,blog

求當在水不倒出來的前提下杯子傾斜角度最大時,水面面積。ip

 

題解:ci

(參考https://blog.csdn.net/danliwoo/article/details/53002695

當 $d=1$ 時,是臨界狀況。

當 $d>1$ 時,水面爲一個橢圓,設 $\theta$ 爲水面與杯底的夾角,則 $S = \pi R r = \pi \cdot \frac{1}{cos \theta} \cdot 1 = \frac{\pi}{cos \theta}$。

當 $d<1$ 時,水面爲一個橢圓截取一部分:

若將水此時的形狀,按平行於杯底的方向,分割成若干薄面,每一個薄面的面積爲 $S_0$,則水的體積爲

$V = \int_{0}^{2}S_0dy$;

不難求得

$y_0 = x_0 tan \theta$

$1 + \cos \alpha = x_0$

$S_0 = \pi - \alpha + \sin \alpha \cos \alpha$

上三式,對於 $0 \le \alpha \le \pi$(即 $2 \ge x_0 \ge 0$)均成立。

則水的體積定積分可變爲

$V = \int_{0}^{2}(\pi - \alpha + \sin \alpha \cos \alpha)d[(1 + \cos \alpha)\tan\theta]$

$\tan\theta \int_{\pi}^{\alpha_1}(\pi - \alpha + \sin \alpha \cos \alpha)(- \sin \alpha)d\alpha$

其中 $\alpha_1 = \arccos(\frac{2}{\tan\theta}-1)$。

對上式積分得

$V = \tan \theta [(\pi \cos \alpha) + (\sin \alpha - \alpha \cos \alpha) - \frac{1}{3} \sin^3 \alpha]_{\pi}^{\alpha_1}$

那麼,咱們能夠二分 $\theta$,使得 $V$ 逼近 $\pi d$,從而肯定 $\theta$,進而用 $S_{斜面} = \frac{S_{底面}}{cos \theta}$ 求得水面面積。

 

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-12;
inline bool equ(double x,double y){return fabs(x-y)<eps;}
inline double a_t(double t) {
    double tmp=2.0/tan(t);
    if(tmp>2) tmp=2.0;
    else if(tmp<0) tmp=0.0;
    return acos(tmp-1.0);
}
inline double I(double a) {
    return pi*cos(a)+sin(a)-a*cos(a)-pow(sin(a),3)/3.0;
}
inline double V(double t) {
    if(equ(t,pi/2.0)) return 0;
    else return tan(t)*(I(a_t(t))-I(pi));
}
int main()
{
    int T;
    double d;
    cin>>T;
    while(T--)
    {
        cin>>d;
        if(equ(d,0))
        {
            printf("%.5f\n",0);
            continue;
        }
        if(d>1)
        {
            printf("%.5f\n",pi/cos(atan(2-d)));
            continue;
        }

        double l=pi/4.0, r=pi/2.0, t;
        while(r-l>eps)
        {
            t=(l+r)/2;
            if(equ(V(t),pi*d)) break;
            else if(V(t)>pi*d) l=t;
            else r=t;
        }
        double a=a_t(t);
        double S=pi-a+sin(a)*cos(a);
        printf("%.5f\n",S/cos(t));
    }
}
相關文章
相關標籤/搜索