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]灯泡。用相似做,会涉及到二次函数所以用三分法求峰值。画图构造相似三角形会很好做。
关于三分法的一个小结:感觉模板性太强,没有太大可做性(?),而且感觉出题尤其是造数据是比较难的,所以并不常考。但是这种三分找峰值的思路是可以借鉴的,无疑也是强大的。
本文作者:Moyyer_suiy
本文链接:https://www.cnblogs.com/Moyyer-suiy/p/17308879.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步