【算法讲解】三分法

三分法主要用于求解一个函数在某个区间内的极大(极小)值点,类似于二分法做一个比较:

      二分法            三分法

作用:   求解一个函数的零点      求解一个函数的极大(极小)值点

条件    函数在这个区间是单调函数   函数在这个区间是凸(凹)函数

首先对于一个凹函数y=f(x),我们要求它的极小值点。

首先确定它的极小值点所在的区间为[l,r]

计算出两个三分点:

mid=(l+r)/2

mid2=(mid+r)/2

(其实这两个点的位置是灵活的)

此时 l < mid <mid2 < r

计算出对应的函数值 f(mid)和f(mid2)。

当f(mid)<f(mid2)时,则极小值点一定不会在mid2和r之间。

反之f(mid)>f(mid2)时,极小值点一定该不会在l和mid之间。

因此,当f(mid)<f(mid2)时,极小值点在[l,mid2]内。此时令l=l,r=mid2继续计算。

当f(mid)>f(mid2)时,极小值点在[mid,r]内。此时令l=mid,r=r继续计算。

直到这个区间足够小,可以认为l=r时,l就是所求的极小值点。(可接受的误差内)

算法复杂度大约是log1.5((r-l)/eps)

double sanfen(double l,double r){
    double mid,midmid,fmid,fmidmid;
    mid=(l+r)/2;
    midmid=(mid+r)/2;
    fmid=f(mid);
    fmidmid=f(midmid);
    while(r-l>0.00000000001){
        //printf("%lf %lf  %lf %lf
",mid,midmid,fmid,fmidmid);
        if(fmid>fmidmid){
            l=mid;
            mid=midmid;
            fmid=fmidmid;
            midmid=(mid+r)/2;
            fmidmid=f(midmid);
        }else{
            r=midmid;
            midmid=mid;
            fmidmid=fmid;
            mid=(l+midmid)/2;
            fmid=f(mid);
        }
    }
    return fmid;
}
模板1
double f(double a)
{
    /*返回函数值*/
}
double Solve(double MIN,double MAX)//返回极值点
{
    double l = MIN, r = MAX;
    double mid, midmid;
    double mid_f, midmid_f;
    while (l + EPS < r)
    {
        mid = (l + r) / 2;
        midmid = (mid + r) / 2;
        mid_f = f(mid);
        midmid_f = f(midmid);
        // 假设求解最大极值.最小值则取小于号
        if (mid_f >= midmid_f) r = midmid;
        else l = mid;
    }
    return l;
}
模板2

 模板1中稍微优化了一下,每次三分之需要多计算一次函数值,另一次直接利用上次计算出来的。

模板2中直接按照思路。

原文地址:https://www.cnblogs.com/syiml/p/3675214.html