题目
题目描述
相比 wildleopard 的家,他的弟弟 mildleopard 比较穷。他的房子是狭窄的而且在他的房间里面仅有一个灯泡。每天晚上,他徘徊在自己狭小的房子里,思考如何赚更多的钱。有一天,他发现他的影子的长度随着他在灯泡和墙壁之间走到时发生着变化。一个突然的想法出现在脑海里,他想知道他的影子的最大长度。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkixyqO4-1645254464156)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220219143825211.png)]
输入格式
输入文件的第一行包含一个整数 T T T,表示测试数据的组数。
对于每组测试数据,仅一行,包含三个实数 H H H, h h h 和 D D D , H H H 表示灯泡的高度, h h h 表示 mildleopard 的身高, D D D 表示灯泡和墙的水平距离。
输出格式
输出文件共 T T T行,每组数据占一行表示影子的最大长度,保留三位小数。
样例
输入
3
2 1 0.5
2 0.5 3
4 3 4
输出
1.000
0.750
4.000
数据范围与提示
T ⩽ 100 , 1 0 − 2 ⩽ H , h , D ⩽ 1 0 3 , 1 0 − 2 ⩽ H − h T\leqslant 100,10^{-2} \leqslant H,h,D \leqslant 10^3,10^{-2} \leqslant H-h T⩽100,10−2⩽H,h,D⩽103,10−2⩽H−h。
分析
将题目转换为图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-32OZYQAo-1645254464159)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220219144446900.png)]
当人从墙上刚有影子处向右一直走到墙的过程中,影子总长是关于墙上影子的凸函数。
所以是三分!!!!
即求函数 f ( x ) = l 1 + l 2 f(x)=l_{1}+l_{2} f(x)=l1+l2的最大值
求解 l 1 l_{1} l1
l 1 l_{1} l1是很明显的 D − x D-x D−x。
求解 l 2 l_{2} l2
根据粉色和蓝色的三角形是相互相似的,那么 H − l 2 = ( H − h ) × D x H-l_{2}=(H-h) \times \frac{D}{x} H−l2=(H−h)×xD
l 2 = H − ( H − h ) × D x l_{2}=H-(H-h)\times \frac{D}{x} l2=H−(H−h)×xD
l , r l,r l,r初值设定
由于 l 2 > 0 l_{2}>0 l2>0所以 l l l的初值为: ( H − h ) × D H (H-h)\times \frac{D}{H} (H−h)×HD
我这里有两种解释方法,其实原理是一样的
方法1
因为 l 2 > 0 l_{2}>0 l2>0
所以 H − ( H − h ) × D x > 0 H-(H-h)\times \frac{D}{x}>0 H−(H−h)×xD>0
所以 H × x > ( H − h ) × D H\times x>(H-h)\times D H×x>(H−h)×D
所以 x > ( H − h ) × D H x>(H-h)\times \frac{D}{H} x>(H−h)×HD
方法2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vrWb1hh7-1645254464159)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220219150359576.png)]
如图正是 l 2 = 0 l_{2}=0 l2=0的情况
根据粉色和蓝色的三角形相似可证:
x D = H − h H \frac{x}{D}=\frac{H-h}{H} Dx=HH−h
即 x = ( H − h ) × D H x=(H-h)\times \frac {D}{H} x=(H−h)×HD
Code
#include<bits/stdc++.h>
using namespace std;
int t;
double H,h,D;
double check(double x){
return D-x+H-(H-h)*D/x;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%lf %lf %lf",&H,&h,&D);
double l=(H-h)*D/H;
double r=D;
double lmid,rmid;
while(r-l>1e-6){
lmid=l+(r-l)/3.0;
rmid=r-(r-l)/3.0;
if(check(lmid)>check(rmid))r=rmid;
else l=lmid;
}
printf("%.3lf\n",check(l));
}
return 0;
}