三分搜索-ZOJ LightBulb

开始算法基础学习的第一天

 

今天学习的内容是三分搜索 相对来说很基础的内容(还是觉得脑子不够用)

三分搜索主要用于凸函数查找极大值。

(盗个图)

如图所示 若要查找该函数的最大值 可以考虑和二分法一样的思路,即用L,R两个端点去不断地逼近这个最大点

但是在这里仅用一个mid中值是不够的 因此添加了一个mmid = (mid+R)/2 判断函数在mid和mmid两点的大小就可以进一步判断极值存在于哪一段中

用一个便于理解的办法,我们分成以下两种情况来讨论:

1.mid,mmid在最大值的同一侧:这时更大的那个值更接近极值 比如mid>mmid那么就可以确定(mmid,R)区间内肯定没有极值,因此抛弃它

2.mid,mmid在最大值的两侧:依然是更大的那个值更接近极值 比如mid>mmid那么也可以确定(mmid,R)区间内肯定没有极值

综上 我们判断mid,mmid两点函数值的大小来缩短区间 逼近极值点(具体见代码)

/*三分搜索实例--ZOJ3203:LightBulb*/
# include<iostream>

using namespace std;

const double EPS = 1e-10;//设定精度

double D, H, h;//为了方便计算写成了全局变量

double calc(double x)
{
    return (D - x) + H - D*(H - h) / x;
}//clac函数。根据几何关系推导。

double ternarysearch(double l, double r)
{
    double mid,mmid;

    while (l + EPS < r)
    {
        mid = (l + r) / 2;
        mmid = (mid + r) / 2;

        double mid_value = calc(mid);
        double mmid_value = calc(mmid);

        if (mid_value > mmid_value)
            r = mmid;
        else
            l = mid;
    }

    return l;
}//三分搜索主体部分

int main()
{
    int T;
    double target;

    cin >> T;

    while (T--)
    {
        cin >> H >> h >> D;

        target = ternarysearch(D-D*h/H,D);//注意开始的两个点的取值

        printf("%.3f\n", calc(target));
        
    }

    return 0;
}

对于一道题目 关键还是写出calc函数。。

posted @ 2015-12-09 13:45  DigitalHermit  阅读(270)  评论(0编辑  收藏  举报