ZOJ 3203 Light Bulb 三分
Compared to wildleopard's wealthiness, his brother mildleopard is rather poor. His house is narrow and he has only one light bulb in his house. Every night, he is wandering in his incommodious house, thinking of how to earn more money. One day, he found that the length of his shadow was changing from time to time while walking between the light bulb and the wall of his house. A sudden thought ran through his mind and he wanted to know the maximum length of his shadow.
Input
The first line of the input contains an integer T (T <= 100), indicating the number of cases.
Each test case contains three real numbers H, h and D in one line. H is the height of the light bulb while h is the height of mildleopard. D is distance between the light bulb and the wall. All numbers are in range from 10-2
Output
For each test case, output the maximum length of mildleopard's shadow in one line, accurate up to three decimal places..
Sample Input
3 2 1 0.5 2 0.5 3 4 3 4
Sample Output
1.000 0.750 4.000
題意:求出人最長的影子L是多少
思路:1.影子可以在地上與牆上。
2.由於影長從燈下0一直到恰好沒投影到牆上的過程是一個單調的過程,我們可以把這段忽略,直接求解投影到牆上後,影長的變化即可。
3.人在燈下的影子長度是0,這時他如果向前走的話,影子會逐漸變長,到最後人走到牆的位置的時候,影長度便是人的身高了,所以影長的變化曲線要麼是單調遞增的,要麼是向上凸的,所以適合三分。(二分法作為分治中最常見的方法,適用於單調函式,逼近求解某點的值,當函式是凸性函式時,就得用三分)。
4.根據相似三角形可以推出left=D-h*D/H(肯定為單調遞增的那部分最大的結果) right=D,
5.設投到牆上的影子為k,人距離燈為x由相似三角形可得k=H-(H-h)*D/x,所以L=k+D-x
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
double H,h,D;
const double eps=1e-8;
double cal(double x)
{
return D-x+H-(H-h)*D/x;
}
double three(double l,double r)
{
double left=l,right=r,mid1,mid2;
while(left+eps<right)
{
mid1=(left+right)/2.0;
mid2=(mid1+right)/2.0;
if(cal(mid1)>=cal(mid2))
right=mid2;
else
left=mid1;
}
return cal(right);
}
int main()
{
int icase;
scanf("%d",&icase);
while(icase--)
{
scanf("%lf%lf%lf",&H,&h,&D);
double l=D-h*D/H,r=D;
double ans=three(l,r);
printf("%.3lf\n",ans);
}
return 0;
}