【三分】【清华集训2015】灯泡

                                       Light Bulb
                    Time Limit: 1 Second      Memory Limit: 32768 KB

好像只有ZJOI上有,贴个地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3366

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 to 103, both inclusive, and H - h >= 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

分析:三分法分一下,模板题,注意考虑多种情况。我枚举的答案是在地上的影子的长度(通过相识三角形可以求出在墙上的影子的长度,只要墙上有影子)。
第一种情况:
墙上没影子,如下图
这里写图片描述
第二种情况:
墙上有影子,如下图
这里写图片描述
无论哪种情况,通过已知量和我们枚举的在地面上的影子的长度都可以求出来x,最终判断一下(x+D-地面上影子的长度>D)是否为true就可以知道是哪种情况了,从而做出相应的对策,具体见代码,有注释。

#include<bits/stdc++.h> 
using namespace std; 
double h,H,d,Left,Right,rMid,lMid,a; 
inline double f(double x) 
{ 
    double y=h*(d-x)/(H-h); //这里的y即是图片中的x,这里的x即是地面上影子的长度
    if(y+d-x>d) //第二种情况
    { 
        return x+(h*d-H*x)/(d-x); //通过相识三角形化简求出影子总长度,可用图中的辅助线得出
    } 
    else 
    { 
        return y; //第一种情况
    } 
} 
int main() 
{ 
    int t; 
    scanf("%d",&t); 
    while(t--) 
    { 
        scanf("%lf%lf%lf",&H,&h,&d); 
        Left=0,Right=d; 
        while(Right-Left>0.0001) //题目精度范围三分
        { 
            lMid=Left+(Right-Left)/3; 
            rMid=Right-(Right-Left)/3; 
            if(f(lMid)<=f(rMid)) Left=lMid; 
            else Right=rMid; //三分模板
        } 
        printf("%.3lf\n",f(Left)); //注意最后要输出影子的长度
    } 
    return 0; 
}

谢谢各位。

posted @ 2018-07-10 18:45  最爱丁珰  阅读(40)  评论(0编辑  收藏  举报