*zoj

来源:互联网 发布:海森伯格矩阵是什么 编辑:程序博客网 时间:2024/06/04 17:48

题目描述

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 H, h 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

三分法介绍

这里写图片描述
注意

  • 三分法多用在求凹凸函数,求最值。
  • 二分法多用在单调函数求值。
  • 凹凸判断
    • 在图像上任取两点A,B连接,若函数图像在两点间的部分均在直线下方,则把该函数在[A,B]之间的部分定义为凹函数.反之为凸函数。
    • 凹函数:f”(x)>=0原函数为凹函数
      凸函数:f”(x)<=0原函数为凸函数

在 Left 和 Right 取两个点 mid1 和 mid2,把该区间分成三个部分

  • 如果f(mid1)≥f(mid2),则峰值在区间 [Left, mid2] 之间
  • 如果f(mid1)< f(mid2),则峰值在区间 [mid1,Right] 之间

注意:如果是凸函数,上面两个条件恰好相反。 可以看到,每次处理后区间少了一个部分,反复下去,直至区间缩小到满足 精度要求。
mid1 和 mid2 常见有两种取法:

  • mid1=(Left+Right)/2 ,mid2=(mid1+Right)/2,最坏的情况下总是剩下 原区间的 3 4,时间复杂度为O(log4 3n)
  • mid1=Left + (Right - Left)/3 mid2=Right - (Right - Left)/3, 这样总是 剩下原来区间的 2 3,时间复杂度为O(log3 2n)

题解

这里写图片描述

三分法

#include<cstdio>#include<iostream>#include<algorithm>#include<cmath>using namespace std;double H,h,D;const double eps=1e-8;double f(double x){    return D-x+H-(H-h)*D/x;}double ternary_search(double L,double R){    if(L>R) swap(L,R);    double mid1,mid2;    while(R-L>eps){        mid1=(L+R)/2.0;        mid2=(mid1+R)/2.0;        if(f(mid1)>=f(mid2))            R=mid2;        else            L=mid1;    }    return f(R);}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%lf%lf%lf",&H,&h,&D);        double l=D-h*D/H,r=D;        double ans=ternary_search(l,r);        printf("%.3lf\n",ans);    }    return 0;}
原创粉丝点击