输入格式
输入文件的第一行包含一个整数 T ,表示测试数据的组数。
对于每组测试数据,仅一行,包含三个实数 H,h 和 D,H 表示灯泡的高度,h 表示 mildleopard 的身高,D 表示灯泡和墙的水平距离。
输出格式
输出文件共 T 行,每组数据占一行表示影子的最大长度,保留三位小数。
样例
样例输入
3
2 1 0.5
2 0.5 3
4 3 4
样例输出
1.000
0.750
4.000
数据范围与提示
T≤100,1e−2≤H,h,D≤1e3, 1e-2<=H-h
本题的关键算法呢,是肥肠简单的三分(注意哦,我们这里可不是三分答案,而是三分人到墙的距离,设为x)
当人的影子头部恰好在墙角时,由相似三角形可得h/H=x/D
那么当x<=h*D/H时,墙上的影子(即下图中的粉色线段)长度为H-(H-h)*D/(D-x),那影子总长就是x+(H-(H-h)*D/(D-x))
(不太明白可以看看下面的图,图中两个黄色三角形相似)
而当x>h*D/H时,地上的影子(同样是下图中的粉色线条,两个黄色的三角形也同样相似)长度为x+((D-x)* H/(H-h))-D;
(为了避免颜色重合,有些线条上下分离了,但其实是在一条直线上的)
那么具体看代码吧
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e6+5; 4 int n; 5 int m,q,ans,p,tot; 6 double H,D,h; 7 int read() 8 { 9 int f=1;char ch; 10 while((ch=getchar())<'0'||ch>'9') 11 if(ch=='-')f=-1; 12 int res=ch-'0'; 13 while((ch=getchar())>='0'&&ch<='9') 14 res=res*10+ch-'0'; 15 return res*f; 16 } 17 void write(int x) 18 { 19 if(x<0) 20 { 21 putchar('-'); 22 x=-x; 23 } 24 if(x>9)write(x/10); 25 putchar(x%10+'0'); 26 } 27 double f(double x) 28 { 29 if(x<=h*D/H) return x+(H-(H-h)*D/(D-x));//此时墙上也有影子 30 else return x-D+((D-x)* H/(H-h));//此时墙上莫得影子 31 } 32 int main() 33 { 34 int t;t=read(); 35 while(t--) 36 { 37 scanf("%lf%lf%lf",&H,&h,&D); 38 double l=0,r=D; 39 while(r-l>1e-11) 40 { 41 double lmid=l+(r-l)/3,rmid=r-(r-l)/3; 42 if(f(lmid)<f(rmid))l=lmid; 43 else r=rmid; 44 } 45 printf("%.3lf\n",f(l)); 46 } 47 return 0; 48 }