一本通题解——1438:灯泡
题目链接
一本通OJ:http://ybt.ssoier.cn:8088/problem_show.php?pid=1438。
我的OJ:http://47.110.135.197/problem.php?id=4473。
题目
题目描述
相比 Wildleopard 的家,他的弟弟 Mildleopard 比较穷。他的房子是狭窄的,而且在他的房间里仅有一个灯泡。每天晚上,他徘徊在自己狭小的房子里,思考如何赚更多的钱。有一天,他发现他的影子的长度随着他在灯泡和墙壁之间走动时会发生变化。一个突然的想法出现在他的脑海里,他想知道在房间里他的影子的最大长度。
输入
输入文件的第一行包含一个整数 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,0.01 ≤ H, h, D ≤1000,0.01 ≤ H − h。
分析
数学相关
相似三角形。
题目分析
首先这是一个数学题,求的是影子长度。我们来讨论一个影子的可能:
1、影子并未碰到墙壁。如下图所示,这需要使用三角形的相似来解决。
如上图所示的情况,此时的相似比为 ,其中 h 表示 Mildleopard 的身高,那么影子的长度即为 。
2、影子有一部分在墙壁上。如题目描述给的图所示。这就需要用两次相似来求影子在墙壁上的长度,如下图所示。
如上图所示的情况,利用直角构造两个三角形,当 Mildleopard 站在离灯泡 x 水平距离时,他与墙的距离即为D−x,那么这两个相似三角形的相似比即为 。我们知道灯泡的高度与 Mildleopard 高度差为 H-h ,然后就可以计算出下面的三角形的较短边的长度为 ,这样我们就可以算出在墙上的影子的长度为,那么整个影子的长度为 。
很明显,影子的两种可能都是单调的,合起来就是一个单峰函数。
算法思路
三分查找
那么问题就简单了,因为是浮点数计算,构造一个三分查找,注意要卡一下精度。套用标准浮点数三分查找模板,从 0 到 D 的范围内查找,实现 check 函数即可。
AC 参考代码
#include <bits/stdc++.h>
using namespace std;double H, h, D;//由于check函数需要用的,就用全局变量吧double check(double x) {if ((H-h)/x*(D-x)>h) {//灯的高度小于影子到墙底部距离。属于第二种情况return x/(H-h)*h;} else {//属于第一种情况return D-x+h-(H-h)/x*(D-x);}
}int main() {int t;cin>>t;int i, j;for (i=0; i<t; i++) {cin >> H >> h >> D;//三分查找double eps = 1e-8;double left=0;double right=D;double l_mid, r_mid;while (left+eps<right) {l_mid = left+(right-left)/3;r_mid = right-(right-left)/3;if (check(l_mid) > check(r_mid)) {right = r_mid;} else {left = l_mid;}}printf("%.3lf\n", check(left));}return 0;
}
直接计算
我们进一步用数学进行分析。假设图中对应的角度为 ,如果墙上有影子,那么函数关系可以推导出。问题就变成如何求极值问题,那么有以下几种关系:
1、如果 ,答案为 。
2、如果 ,答案为 。
3、否则答案为 。
那么对应的代码就更简单了。
AC 参考代码
#include <cstdio>
#include <cmath>int main() {int t;scanf("%d", &t);for (int i=0; i<t; i++) {double H, h, D;scanf("%lf %lf %lf", &H, &h, &D);double ans = D-h*D/H;double val = sqrt((H-h)*D);if (ans<=val && D>val) {ans = D+H-2*val;} else if (val<ans) {ans = h*D/H;} else {ans = h;}printf("%.3lf\n", ans);}return 0;
}
一本通题解——1438:灯泡相关推荐
- 信息学奥赛一本通(题解目录)
信息学奥赛一本通(题解目录) 记录了我从初学者到逐渐熟悉c++的成长之路 信息学奥赛一本通OJ 目录 信息学奥赛一本通(题解目录) 前言 一.语言及算法基础篇 基础(一) C++语言 第一章 C++语 ...
- 一本通题解——1251:仙岛求药
题目相关 题目链接 一本通 OJ,http://ybt.ssoier.cn:8088/problem_show.php?pid=1251. 计蒜客 OJ,https://nanti.jisuanke. ...
- 一本通题解——1191:流感传染
题目相关 题目链接 一本通 OJ,http://ybt.ssoier.cn:8088/problem_show.php?pid=1191. 题目描述 有一批易感人群住在网格状的宿舍区内,宿舍区为 n* ...
- 一本通题解——1433 愤怒的牛
题目链接 一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid=1433. 自己OJ:http://47.110.135.197/problem.php ...
- 信息学奥赛一本通 题解目录
刷题 很全的知识体系 转载:https://blog.csdn.net/u011815404/article/details/79324003 第一部分 C++语言 第一章 C++语言入门 T1001 ...
- 1000:入门测试题目--信息学奥赛一本通题解
[题目描述] 求两个整数的和. [输入] 一行,两个用空格隔开的整数. [输出] 两个整数的和. [输入样例] 1 2 [输出样例] 3 [来源] NO 分析:入门题,读入用cin,scanf,rea ...
- 快乐地打牢基础(1)——二分与三分
二分是一种常用且非常精妙的算法,常常是我们解答问题的突破口.二分的基本用途是在单调序列或单调函数中做查找操作.因此当问题的答案具有单调性时,就可以通过二分把求解转换为判定(根据复杂度理论,可知判定的难 ...
- OpenJudge NOI题库 1.4 编程基础之逻辑表达式与条件分支
OpenJudge NOI题库 1.4 编程基础之逻辑表达式与条件分支 OpenJudge - OpenJudge - 题目 啊哈C语言 第11讲 4.1.4_01判断数正负 啊哈C语言 第11讲 4 ...
- 灯泡(信息学奥赛一本通 1438)
题目描述 相比 wildleopard 的家,他的弟弟 mildleopard 比较穷.他的房子是狭窄的而且在他的房间里面仅有一个灯泡.每天晚上,他徘徊在自己狭小的房子里,思考如何赚更多的钱.有一天, ...
最新文章
- golang 随机数 实现
- ubuntu 安装git
- Overload 和Override 的区别
- 【CF#706B】 Interesting drink (二分)
- 运行Java web时遇到的错误
- 信号 移相 matlab,MATLAB中的SISOTOOL在数字式移相全桥中的应用
- 数据可视化美学形式与功能需要齐头并进
- socket通信基础
- 019,Intelidea右键新建选项没有Java class选项
- POJ3263 Tallest Cow【差分数组】
- Few-shot learning和Meta-learning
- 网络的小区号和网络tac_网络问政|城基路老旧小区排污管长期堵塞没人管?
- linux gnu编译器下载,GNU Compiler Collection(gcc编译器)下载_GNU Compiler Collection(gcc编译器)官方下载-太平洋下载中心...
- C++ 偏微分数值计算库_「首席架构师推荐」数值分析软件精选
- 计算机如何解锁 磁盘,怎么解除Dell电脑硬盘的bitlocker加密
- 【随手写】JS过滤所有script正则
- 2019年全国大学生电子设计大赛(简单电路特性测试仪)
- 解决表格刷新时抖动闪烁问题
- Intel GPA 参数
- 直连式SAS/SATA存储+超高清视频