ZOJ 3203 Light Bulb

来源:互联网 发布:淘宝虚假交易新规 编辑:程序博客网 时间:2024/06/06 04:24

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

题意大致为,人站在灯下,给灯高,人高,等离墙距离,求影子在地上和墙上的长度总和。

思路。设灯到人的水平距离为d。在影子到达墙之前,也就是d=D-(Dh/H)时,显然影子长度是单调增。所以只要求从此点,到人站到墙处的影子最大值。
设投在墙上的影子高x,过人头顶和墙上的影子顶端,各作一条水平线,得到(H-h)/d=(H-x)/D。
所以,影子在墙上的高度为:H-D(H-h)/d。加上地上的影子长度D-d。则影子的总长度L=D-d+H-D*(H-h)/d。判断其为一个凸函数,故使用三分法。对于每个lmid和rmid,判断哪个的影子长,然后不断三分。
代码如下:

#include<stdio.h>#include<iostream>#include<cmath>using namespace std;int T;double H,h,D,l,le,ri;const double eps=1e-9;double f(double d){    return D-d+H-D*(H-h)/d;}int main(void){    scanf("%d",&T);    while(T--){        scanf("%lf%lf%lf",&H,&h,&D);        le=D-D*h/H;        ri=D;        while(ri-le>eps){            double lmid=(le+ri)/2.0;            double rmid=(lmid+ri)/2.0;            if(f(lmid)-f(rmid)<0)                le=lmid;            else                ri=rmid;        }        printf("%.3lf\n",f(le));    }    return 0;}
原创粉丝点击