[清华集训2015]灯泡Zjoi3203 Light Bulbs

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.

Input

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

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

Output

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

Sample Input

3
2 1 0.5
2 0.5 3
4 3 4

Sample Output

1.000
0.750
4.000
算了扔个 链接
题目大意:

有一个人在灯和墙之间移动,问移动到那一点的时候影子的长度最长,有图有真相,可以看上面那副图理解一下。

分析

这一题乍一看以为是贪心,后面想了想,是道数学题……

算影子的长度可以用相似三角形,相信各位上过初中的朋友都会。。

那么我们发现这是一个单峰函数,要求峰值,这里我们可以用一个很强大的东西,三分法。

嗯,没错,差不多就是这样了。

详情请看代码:

#include<bits/stdc++.h>
using namespace std;
const double MIN=0.00001;
double tanA,H,h,d,D,m1,m2;
double get_len(double a){
	tanA=(H-h)/a;//这里大家可以画个图帮助理解
	D=H/tanA;//下面那条的长(在没有墙的情况下)
	if(D<=d) return D-a;//如果没到墙,就直接返回地上影子的长度。
	D=D-d;
	return d-a+D*tanA;//d-a是地上影子的长度D*tanA是墙上影子的长度.
}
int t;
int main()
{
 	cin>>t;
 	while(t--){
 		cin>>H>>h>>d;
 		double l=0,r=d;
 		int p=100;//控制三分的次数,这样子写比较好控制时间复杂度,也不用为精度担忧。
 		while(p--){//三分模板,还是挺容易理解的,大不了上百度。我三分的值是人到灯垂直下来那条线的距离。
 			m1=l+(r-l)/3;
 			m2=r-(r-l)/3;
 			if(get_len(m1)<get_len(m2)) l=m1;
 			else r=m2;
		 }
		 printf("%.3f\n",get_len(l));
	 }
   return 0;
}

切掉perfectly!

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/80870928