題目大意
這個題就是講有一個小孩子非常淘氣特別喜歡捉弄別人,然后有一次他在家開party的時候就想玩個小游戲去搞別人事情。這個游戲就是我們以前玩的有三個杯子,只有一個杯子里面有球,那個小孩通過不斷的交換球的位置來干擾你然后最后停下叫你猜哪個杯子有球,那個小孩為了保證別人永遠猜不對就往杯子里面放膠水讓球黏上去。他只會在杯子內部黏膠水(底部不黏),按照如下順序給你杯子尺寸,r,R,h,問你最大可以放多大個球進去。
其實這題蠻簡單的但是我當時一直想不出來再加上我看到個好思路于是就打算寫下這篇題解。
杯子.png
樣例輸入
3 4 8
樣例輸出
3.531128874149
分析
這題可以用兩種辦法解。
1.推導公式硬算,公式很好推就是把中間的剖面補全成三角形計算三角形內切圓的半徑如果小于h/2直接輸出,如果大于h/2答案就是h/2。
2.通過不斷地利用二分法篩選出能放進去的最大的球的體積。在h/2與0之間不斷二分直到誤差小于1e-6。而判斷方法就是檢查半徑是否小于圓心到側邊的距離。如果小于當然放得下。而我認為此方法是比較符合題意的辦法。
代碼如下。
#include<cmath>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps = 1e-6;
bool judge(double x,double r, double R, double h)
{
double seta1 = atan(h/(R-r));
double seta2 = atan(x/R);
double seta3 = seta1 - seta2;
double AO = sqrt(x*x+R*R);
double temp = AO*sin(seta3);
if(temp >= x) return true;
else return false;
}
int main()
{
double h,r,R;
scanf("%lf%lf%lf",&r,&R,&h);
double low = 0;
double high = h/2.0;
int con = 0;
while(high - low >= eps)
{
double mid = (high+low)/2.0;
if(judge(mid,r,R,h))
{
low = mid;
}
else high = mid;
}
printf("%.7lf",low);
}