三分法

1.三分法模板

double Calc(Type a)
{
    /* 根据题目的意思计算 */
}

void Solve(void)
{
    double Left, Right;
    double mid, midmid;
    double mid_value, midmid_value;
    Left = MIN; Right = MAX;
    while (Left + EPS < Right)
    {
        mid = (Left + Right) / 2;
        midmid = (mid + Right) / 2;
        mid_value = Calc(mid);
        midmid_value = Calc(midmid);
        // 假设求解最大极值.
        if (mid_value >= midmid_value) Right = midmid;
        else Left = mid;
    }
}

 

2.两重三分法

XMU.1125.越野车大赛

#include <math.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#define INF 0x7fffffff
#define eps 1e-5

int n, m, s1, s2, s3;

double Calc(double x, double y)                 /* x, y, n-x-y分别表示三段横向距离 */
{ return sqrt(pow(m,2)+pow(x,2))/s1 + sqrt(pow(m,2)+pow(y,2))/s2 + sqrt(pow(m,2)+pow(n-x-y,2))/s3; }

int main()
{
    double ans = INF;
    scanf("%d %d %d %d %d", &n, &m, &s1, &s2, &s3);
    double XL, XR, XM, XMM, Xt1, Xt2;
    double YL, YR, YM, YMM, Yt1, Yt2;

    XL = 0; XR = n;                       /* 外层对y取值透明,x为唯一变量时推极小值 */
    while(XR - XL > eps)
    {
        XM = (XL + XR) / 2;
        XMM = (XM + XR) / 2;

        YL = 0; YR = n;                      /* 当x固定为XM,y为唯一变量时推极小值 */
        while(YR - YL > eps)
        {
            YM = (YL + YR) / 2;
            YMM = (YM + YR) / 2;

            Yt1 = Calc(XM, YM);
            Yt2 = Calc(XM, YMM);
            if(Yt1 > Yt2)
                YL = YM;
            else YR = YMM;
        }
        Xt1 = Calc(XM, YL);                  // 或Xt1 = Calc(XM, YR);


        YL = 0; YR = n;                      /* 当x固定为XMM,y为唯一变量时推极小值 */
        while(YR - YL > eps)
        {
            YM = (YL + YR) / 2;
            YMM = (YM + YR) / 2;

            Yt1 = Calc(XMM, YM);
            Yt2 = Calc(XMM, YMM);
            if(Yt1 > Yt2)
                YL = YM;
            else YR = YMM;
        }
        Xt2 = Calc(XMM, YL);                 // 或Xt2 = Calc(XMM, YR);

        if(Xt1 > Xt2)
        { XL = XM; ans = Xt2; }
        else
        { XR = XMM; ans = Xt1; }
    }
    printf("%.10f\n", ans);
    return 0;
}

思路分析:

从Calc公式不难看出函数图像在x-y-z三维坐标中是一个下凸曲面,现在题目要求转换为:找到曲面最低处(x', y'),使得z = Calc(x', y')达到最小,解决这类三维图像(二元)求极值问题就是转化成二维图像(一元)求极值问题,就可以用普通三分法求解,这里采用两重三分法,外层用来逐步逼近目标x',内层用来逐步逼近目标y':

当x固定在某值时,用普通三分法再确定y求得当前最小值是很容易做到的……在这一系列最小值的集合再选最小值事实上又是一个二维图像(一元)求极值问题,这可以从曲面的纵向剖物面看出,那么程序内外层就是依据这个思路编写的。

posted on 2015-07-16 12:00  huashunli  阅读(257)  评论(0编辑  收藏  举报

导航