【C++】「一本通 1.2 练习 3」灯泡(Light Bulb)

【来源】

一本通题库-1438
LibreOJ-10016
ZOJ-3203
vjudge

【题目描述】

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.

相比 wildleopard 的家,他的弟弟 mildleopard 比较穷。他的房子是狭窄的而且在他的房间里面仅有一个灯泡。每天晚上,他徘徊在自己狭小的房子里,思考如何赚更多的钱。有一天,他发现他的影子的长度随着他在灯泡和墙壁之间走到时发生着变化。一个突然的想法出现在脑海里,他想知道他的影子的最大长度。
在这里插入图片描述

【输入格式】

The first line of the input contains an integer T ( T < = 100 ) T (T <= 100) T(T<=100), indicating the number of cases.

Each test case contains three real numbers H H H, h h h and D D D in one line. H H H is the height of the light bulb while h h h is the height of mildleopard. D D D is distance between the light bulb and the wall. All numbers are in range from 1 0 − 2 10^{-2} 102 to 1 0 3 10^3 103, both inclusive, and H − h > = 1 0 − 2 H - h >= 10^{-2} Hh>=102.

输入文件的第一行包含一个整数 T T T ,表示测试数据的组数。

对于每组测试数据,仅一行,包含三个实数 H H H h h h D D D H H H 表示灯泡的高度, h h h 表示 mildleopard 的身高, D D D 表示灯泡和墙的水平距离。

【输出格式】

For each test case, output the maximum length of mildleopard’s shadow in one line, accurate up to three decimal places…

输出文件共 T T T 行,每组数据占一行表示影子的最大长度,保留三位小数。

【样例输入】

3
2 1 0.5
2 0.5 3
4 3 4

【样例输出】

1.000
0.750
4.000

【数据范围】

T ≤ 100 T≤100 T100 1 0 − 2 ≤ H , h , D ≤ 1 0 3 10^{−2}≤H,h,D≤10^3 102H,h,D103 1 0 − 2 ≤ H − h 10^{−2}≤H−h 102Hh

【解析】

三分。
当人从墙上刚有影子处向右一直走到墙的过程中,影子总长是关于墙上影子的凸函数。
即求函数 f ( x ) = h ∗ D − H ∗ x D − x + x f(x)=\frac{h*D-H*x}{D-x}+x f(x)=DxhDHx+x(也可以是 f ( x ) = D − x + H − D ∗ ( H − h ) x f(x)=D-x+H-\frac{D*(H-h)}{x} f(x)=Dx+HxD(Hh)) 的最大值。
三分墙上的影子长。

【代码】

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;

typedef long long LL;

const int N=105;
const int inf=1e9;

int T;
double H,h,D;

double calc(double x) {
    
    
	return D-x+H-D*(H-h)/x;
}

int main() {
    
    
	scanf("%d",&T);
	while(T--) {
    
    
		scanf("%lf%lf%lf",&H,&h,&D);
		double l=D-D*h/H,r=D;
		while(r-l>1e-12) {
    
    
			double lmid=l+(r-l)/3;
			double rmid=r-(r-l)/3;
			if(calc(lmid)<calc(rmid)) l=lmid;
				else r=rmid;
		}
		printf("%0.3f\n",calc(l));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Ljnoit/article/details/105793412