0
点赞
收藏
分享

微信扫一扫

三分法 ZOJ 3203 LightBulb

小禹说财 2023-02-07 阅读 94


                                               三分法

算法讲述

¢ 当需要求某凸性或凹形函数的极值,通过函数本身表达式并不容易求解时,就可以用三分法不断逼近求解。

¢ 类似二分的定义Left和Right

mid = (Left + Right) / 2

midmid = (mid + Right) / 2;

如果mid靠近极值点,则Right = midmid;

否则(即midmid靠近极值点),则Left = mid;

例题:

ZOJ 3203 LightBulb

Light Bulb

Time Limit: 1 Second      Memory Limit: 32768 KB

Compared towildleopard's wealthiness, his brother mildleopard is rather poor. His house isnarrow and he has only one light bulb in his house. Every night, he iswandering in his incommodious house, thinking of how to earn more money. Oneday, he found that the length of his shadow was changing from time to timewhile walking between the light bulb and the wall of his house. A suddenthought ran through his mind and he wanted to know the maximum length of hisshadow.

Input

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

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

Output

For each testcase, output the maximum length of mildleopard's shadow in one line, accurateup 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

题目意思:

如图,人左右走动,求影子L的最长长度。

根据图,很容易发现当灯,人的头部和墙角成一条直线时(假设此时人站在A点),此时的长度是影子全在地上的最长长度。当人再向右走时,影子开始投影到墙上,当人贴着墙,影子长度即为人的高度。所以当人从A点走到墙,函数是先递增再递减,为凸性函数,所以我们可以用三分法来求解。

题目分析:

题意是给定如图的H,h,D,求最大的影子L。

如图所示,设X,Y。由三角形相似得,x / y = H / (y + D) 。

解得:y = x * D / (H - x)。

由三角形相似得,x / y = h / (y + L -x)。

带入y,解得 L = x + D *(h - x) / (H - x)。

对L 求一阶导数,并令L ’ = 0,得:

x = H +- sqrt(D * (H - h))。

因为 x 必定小于 H,所以 x = H - sqrt(D * (H - h))。

当 x <= 0 及 x >= h 时,不符合实际意义。

当:x <= 0,带入计算,即 H * H <= D * (H - h),由相似三角形ans = h / H * D。

当:x >= h,带入计算,即 H - h >= D,得最大时即为人靠墙时,ans = h。

代码实现:

 

#include <bits/stdc++.h>
using namespace std;
double H,h,D;
double cal(double x)
{
return x+D*(h-x)/(H-x); //这里放要求的函数;
}
int main()
{
int T;
cin>>T;
while(1)
{ T--;
if(T==0) break;
cin>>H>>h>>D;
double left=0,right=h,mid,midmid;
while(left+1e-9<=right) //精度要求
{
mid=(left+right)/2;
midmid=(mid+right)/2;
if(cal(mid)>=cal(midmid))
right=midmid;
else
left=mid;
}
printf("%.3lf/n",cal(mid));
}
return 0;
}


 

 

 

举报

相关推荐

0 条评论