「一本通 1.2 练习 3」灯泡 (三分

题目

题目描述

相比 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 T100,102H,h,D103,102Hh

分析

将题目转换为图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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 Dx

求解 l 2 l_{2} l2

根据粉色和蓝色的三角形是相互相似的,那么 H − l 2 = ( H − h ) × D x H-l_{2}=(H-h) \times \frac{D}{x} Hl2=(Hh)×xD

l 2 = H − ( H − h ) × D x l_{2}=H-(H-h)\times \frac{D}{x} l2=H(Hh)×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} (Hh)×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(Hh)×xD>0

所以 H × x > ( H − h ) × D H\times x>(H-h)\times D H×x>(Hh)×D

所以 x > ( H − h ) × D H x>(H-h)\times \frac{D}{H} x>(Hh)×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=HHh

x = ( H − h ) × D H x=(H-h)\times \frac {D}{H} x=(Hh)×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;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值