算法——三分法

三分法

简介

三分法求单峰(或单谷)的极值是二分法的简单拓展,单峰(或单谷)可以简单的理解为二次函数含最值的区间,左右两边严格单调,对于这样的二次函数:y = ax2 + bx + c(a≠0),最值在 x = - b/2a 处取得,则给定一个区间,该区间包含这个 x 值,就可以使用三分法求解取得最值的 x 值。

原理

拿上面的二次函数举例,若二次项系数a大于0,则该二次函数的图像是一个单谷,给定区间包含最值点 x = - b/2a ,则我们可以将该区间三等分,左三等分点为 m i d L midL midL ,右三等分点为 m i d R midR midR
m i d L midL midL 对应的函数值大于 m i d R midR midR 对应的函数值,则有两种情况:第一种是 m i d L midL midL m i d R midR midR 都在最值点的左边,第二种是 m i d L midL midL 在最值点的左边,而 m i d R midR midR 在最值点的右边。可见,两种情况都是 m i d L midL midL 在最值点左边。
m i d L midL midL 对应的函数值小于 m i d R midR midR 对应的函数值,则有两种情况:第一种是 m i d L midL midL m i d R midR midR 都在最值点的右边,第二种是 m i d L midL midL 在最值点的左边,而 m i d R midR midR 在最值点的右边。可见,两种情况都是 m i d R midR midR 在最值点右边。
结合上面两个推断,可以得出一个策略:对于二次项系数a大于0的二次函数,当 m i d L midL midL 对应的函数值大于 m i d R midR midR 对应的函数值时,让子区间的左端点取 m i d L midL midL ;当 m i d L midL midL 对应的函数值小于 m i d R midR midR 对应的函数值时,让子区间的右端点取 m i d R midR midR 。这样可以保证在缩小区间的时候让最值点一直在区间内。
对于二次项系数a小于0的二次函数,结论刚好是相反的。

复杂度

每次将长度为 n n n 的区间缩小为 1/3 ,算法的时间复杂度为 O(log3n) 。

建模

对于三分法能解决的问题,最难的是建立一个单峰(或单谷)函数,其它的有如下的模版:

// type_name是基本数据类型中 整型 或 浮点型 的一种,根据精度和题目而改变
type_name func_x(type_name x); // 根据传入的x取其对应的函数值
type_name left, right, midL, midR;
// 接收left和right的值
while ( /* 条件,实数三分和整数三分不同 */ )
{
	midL = left + (right - left) / 3;
	midR = right - (right - left) / 3;
	if (func_x(midL) > func_x(midR))
		// left = midL; 或 right  = midR; 根据函数的单调性而改变
	else
		// right  = midR; 或 left = midL; 根据函数的单调性而改变
}
// 输出结果

实数三分

对于实数三分,我们可以提前设置一个精度,当区间长度(即 右端点 - 左端点)小于精度时,退出循环,区间左端点就是结果。
例题如下:
【模板】三分 (P3382)

整数三分

对于整数三分,当区间长度小于 2 2 2 时,退出循环,然后在区间的三个值对应的函数值中枚举最值。
例题如下:
期末考试 (洛谷P3745)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值