第1部分 基礎算法(提高篇)--第2章 二分與三分1438:燈泡

1438:燈泡

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 442 通過數: 295
【題目描述】
相比wildleopard的家,他的弟弟mildleopard比較窮。他的房子是狹窄的而且在他的房間裏面僅有一個燈泡。每天晚上,他徘徊在自己狹小的房子裏,思考如何賺更多的錢。有一天,他發現他的影子的長度隨着他在燈泡和牆壁之間走到時發生着變化。一個突然的想法出現在腦海裏,他想知道他的影子的最大長度。

【輸入】
第一行包含一個整數T(T≤100),表示測試數據的組數。

對於每組測試數據僅一行包含三個實數H,h和D,H表示燈泡的高度,h表示mildleopard的身高,D表示燈泡和牆的水平距離。10−2≤H,h,D≤103,H−h≥10−2。

【輸出】
共T行,每組數據佔一行表示影子的最大長度,保留三位小數。

【輸入樣例】
3
2 1 0.5
2 0.5 3
4 3 4
【輸出樣例】
1.000
0.750
4.000
【提示】
【數據規模】

對100%的數據,T≤100,10−2≤H,h,D≤103,10−2≤H−h。


思路:在這裏插入圖片描述
**最簡單的就是L1,L1的長度就等於D-x(x表示這個人走的距離,D表示總長度)
接着最複雜的就是L2,求這個L2要用到相似三角形.
這個三角形A與三角形B相似,所以三角形A的長的那一條直角邊和三角形B的長的那一條直角邊的比值是固定的,爲D:X=D/x.
然後三角形B的短直角邊的長度爲H-h,那麼根據比值,三角形A的短直角邊的長度就爲(H-h)*D/x.
然後這個三角形A所在的短直角邊我們已經求出來了,那麼下面的那個L2就很好求了,總長是H,上面的長度爲(H-h)*D/x,下面L2的長度就爲H-(H-h)*D/x
L1和L2的長度我們都找到了公式之後,就交給三分判斷這個人走到哪個位置的時候的影子長度是最大的。總的長度爲L1+L2
還有一個點要注意的是,在計算影子的時候,要保證牆上一定有影子,不然會出現負數,所以 l(就是三分的最小邊界) 要從(H-h)*D/H開始。
推導過程:
一開始L2=H-(H-h)*D/x,然後我們又要L2>0,所以H-(H-h)*D/x>0
H-(H-h)*D/x>0
H>(H-h)*D/x
Hx>(H-h)*D
x>(H-h)D/H
所以這個最小邊界爲(H-h)D/H
最大邊界就是D的距離,因爲他只能走這麼多

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double H,D,h;
double check(double x)//我們走到的點的位置 
{
	double L1 = (D-x);
	double L2 = H-(H-h)*D/x;
	return L1 + L2;
}
int main()
{
	int T; scanf("%d",&T);
	while(T--)
	{
		scanf("%lf%lf%lf",&H,&h,&D);
		double l = (H-h)*D/H,r=D;//l,r表示的是人走的距離 
		//l要從(H-h)*D/H開始,不然牆上沒有影子
		//人走的最大距離自然就是D 
		while(r-l >= 1e-9)
		{
			double mid1 = l+(r-l)/3.0,mid2 = r-(r-l)/3.0;//三分
			if(check(mid1) > check(mid2)) r=mid2;//求最小
			else l = mid1;
		}
		printf("%.3lf\n",check(r));
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章