4.12 三分法学习笔记

三分的思路和二分有一点像。正好这两天数学在学函数的单调性,所以感觉还不错。但是三分法出题似乎有一定的局限性,所以应用并不广泛,但是还是需要学习一下。


三分板子,洛谷:P3382 【模板】三分法 三分求单峰函数极值。

三分适用的情况:有唯一的最大值,满足最大值左侧严格单调递增,右侧严格单调递减(或左减右增)。强调严格单调,这样在确定最值是才能判断最值的位置,否则三分法不能缩小左右边界。

此处以该题为例,即该单峰函数存在最大值,最大值左侧严格单调递增,最大值右侧严格单调递减。

不妨将当前所找的区间 [l, r] 用 lmid 与 rmid 划分为三个区间,lmid < rmid。

此时 f(lmid) > f(rmid) 会有两种情况:1.lmid 与 rmid 均在最值右侧;2.lmid 在最值左侧,rmid 在最值右侧。

会发现无论是哪种情况,rmid 都在最值的右侧,那么我们就可以将所寻找的区间缩小,即使 r = rmid。同理,当 lmid > rmid 时使 l = lmid。

其他没什么需要特别注意的。鉴于本题涉及到浮点数,所以关注一下判断两个浮点数相同时,相减,若差小于一个很小的数即可(精度一般 1e-6 或 1e-7 就行)。

#include<bits/stdc++.h>
#define db double
using namespace std;
const db eps = 1e-7;
int n;
db a[15];
db l, r, midl, midr;
db f(db x)
{
    db s = 0;
    for(int i = n; i >= 0; i -- ) s = s * x + a[i];
    return s; 
}
int main()
{
    scanf("%d%lf%lf", &n, &l, &r);
    for(int i = n; i >= 0; i -- ) scanf("%lf", &a[i]);
    while(r - l > eps)
    {
        midl = l + (r - l) / 3.0;
        midr = r - (r - l) / 3.0;
        if(f(midl) > f(midr)) r = midr;
        else l = midl;
    }
    printf("%.5lf", l);
    return 0;
}

板子推荐 洛谷 P5931 [清华集训2015]灯泡。用相似做,会涉及到二次函数所以用三分法求峰值。画图构造相似三角形会很好做。

关于三分法的一个小结:感觉模板性太强,没有太大可做性(?),而且感觉出题尤其是造数据是比较难的,所以并不常考。但是这种三分找峰值的思路是可以借鉴的,无疑也是强大的。

posted @ 2023-04-12 10:13  Moyyer_suiy  阅读(61)  评论(0编辑  收藏  举报