1. 程式人生 > >【三分】【清華集訓2015】燈泡

【三分】【清華集訓2015】燈泡

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

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; 
}

謝謝各位。