三分查找算法

news2024/9/23 15:19:17

目录

一 算法简介

详细介绍

两种基本方法

二 算法实践

1)实数三分

拓展:秦九韶算法计算多项式

方法1:直接模拟累加

 方法二:根据秦九韶算法

1)模板三分法

题目描述

解法

2)三分求极值

题目描述

分析

3)Line belt

题目描述

分析

2)整数三分

算法模板

三 题目练习

函数

题目描述

题目分析

题目解答

附录


一 算法简介

详细介绍

三分法求单峰(或单谷)的极值是二分法的简单扩展

        单峰函数和单谷函数如下图所示,函数fx再区间【L,R】内只有一个极值v,再极值点两边函数是单调变化的。以单峰函数为例,在v的左边是严格单调递增的,在右边是严格单调递减的。

                         

下面的讲解都以求单峰极值为例:
         如何求单峰函数最大值的近似值?虽然不能直接用二分法,但是只要稍微变形一下就可以了

        在【L,R】内任取两个点:mid1和mid2,把函数分为3段,有以下情况:

1)若f(mid1)<f(mid2),极值点v一定在 mid1 的右侧

mid1和 mid2 要么都在v的左侧,要么分别在v的两侧,如图所示。下一步,令L=mid1,区间从[L,r]缩小为[mid1,r],然后再继续把它分成3段.

                        

2)若f(mid1)>f(mid2),极值点 一定在 mid2 的左侧,如图所示

下一步,令r=mid2,区间从[l,r ]缩小为[l,mid2]

        ​​​​​​​        ​​​​​​​        

不断缩小区间,就能使区间[l,r]不断逼近 ,从而得到近似值

如何取 mid1和 mid2?

两种基本方法

(1)三等分: mid1 和 mid2 为[l,r]的三等分点,那么区间每次可以缩小 1/3

(2)近似三等分:计算[l,r]中间点 mid=(+r)/2,然后让 mid1 和 mid2 非常接近mid,如mid1=mid-eps,mid2=mid+eps,其中 eps 是一个很小的值,那么区间每次可以缩小接近一半。

近似三等分比三等分要稍微快一点。不过,在有些情况下,eps 过小可能导致这两种方 法算出的结果相等,导致判断错方向,所以不建议这么写。从复杂度上看,0(log;n)和 O(logn)是差不多的

注意:

单峰函数的左右两边要严格单调,否则可能在一边有 f(mid1)-=f(mid2),导致无法判断如何缩小区间

二 算法实践

1)实数三分

拓展:秦九韶算法计算多项式

方法1:直接模拟累加

题目条件:n为最高的次数,a数组为系数,x为给定的值。

double f(int n,double a[],double x)
{
    int i;
    double p=a[0];
    for(i=1;i<=n;i++)
        p+=(a[i]*pow(x,i));
    return p;
}

 方法二:根据秦九韶算法

在这里插入图片描述

可转化为:
在这里插入图片描述
故我们可以从内往外递推的计算多项式的值。

double f(int n,double a[],double x)
{
    int i;
    double p=a[n];//从最内层开始
    for(i=n;i>0;i--)
        p=a[i-1]+p*x;
    return p;
}

 两种算法时间复杂度分析:
第一种由于的时间复杂度大致为O(N)=n²。若将pow函数改为快速幂函数,则可优化为O(N)=n(logn);
第二种的时间复杂度为O(N)=n;

1)模板三分法

题目描述

如题,给出一个 N 次函数,保证在范围 [l, r] 内存在一点 x,使得 [l, x] 上单调增,[x, r] 上单调减。试求出 x 的值。

输入格式

第一行一次包含一个正整数 N 和两个实数 l, r,含义如题目描述所示。

第二行包含 N + 1 个实数,从高到低依次表示该 N 次函数各项的系数。

输出格式

输出为一行,包含一个实数,即为 x 的值。若你的答案与标准答案的相对或绝对误差不超过 10^{-5} 则算正确。

样例

输入

3 -0.9981 0.5
1 -3 -3 1

输出

-0.41421

解法

三等分法:mid1和mid2为[l,r]的三等分点

# include <stdio.h>
const double eps = 1e-6;
int n;
double a[15];
double f(double x){
	//计算函数值
	int i;
	double s = 0;
	for(i=n;i>=0;i--)	s = s*x + a[i]; //注意函数求值的写法
	return s;
}


int main(){

	double L,R;
	int i;
	scanf("%d %lf %lf",&n,&L,&R);
	for(i=n;i>=0;i--)
		scanf("%lf",&a[i]);
	while(R-L>eps) // for(int i = 0;i<100;it+)
	{ //用for循环也可以
		double k =(R-L)/3.0;
		double mid1 =L+k,mid2 = R-k;
		if(f(mid1) > f(mid2)) R = mid2;
		else L = mid1;
	}
	printf("%.5f\n",L);
	return 0;
}

近似三等分法:mid1和mid2在[l,r]的中间点附近

# include <stdio.h>
const double eps = 1e-6;
int n;
double a[15];
double f(double x){
	//计算函数值
	int i;
	double s = 0;
	for(i=n;i>=0;i--)	s = s*x + a[i]; //注意函数求值的写法
	return s;
}


int main(){

	double L,R;
	int i;
	scanf("%d %lf %lf",&n,&L,&R);
	for(i=n;i>=0;i--)
		scanf("%lf",&a[i]);
	while(R-L>eps) // for(int i = 0;i<100;it+)
	{ //用for循环也可以
		double mid=L+(R-L)/2;
		if(f(mid-eps) > f(mid)) R = mid;
		else L = mid;
	}
	printf("%.5lf\n",L);
	return 0;
}

2)三分求极值

题目描述

在直角坐标系中有一条抛物线 y-azz+bx+c 和一个点 P(x,y),求点P 到抛物线的最短距离d。
输入:第1行输入5个整数:a,b,c,工;y。a,b,c 构成抛物线的参数,工,y 表示P点
坐标。-200<a,b,c,工,y<200。
输出: 一个实数 d,保留3位小数(四舍五入)。

分析

直接求距离很麻烦,观察本题的距离d,发现满足单谷函数的特征,用三分法即可

3)Line belt

题目描述

给定两条线段 AB、CD,一个人在 AB 上跑时速度为 P,在 CD 上跑时速度为Q,在其他地方跑时速度为 R。求从A 点跑到D 点最短的时间。

输入:第1行输入测试数量 T。对于每个测试输入3行:第1行为4 个整数,表示A点和B点的坐标,即 Ax,Ay,Bx,By; 第2行为4 个整数,表示 C点和D点的坐标,即Cx,Cy,Dx,Dy;第3行为3个整数 P、Q、R。

数据范围:0<Ax,Ay,Bx,By,Cx,Cy,Dx,Dy≤1000,1≤P,Q,R<10

输出:从A 点到D点的最短时间,四舍五入取两位小数。

分析

从A 点出发,先走到线段 AB 上一点 X,然后走到线段 CD上一点Y,后到 D 点,时间为
time=l AX I / P+IXYI/R+IYDI/Q

假设已经确定了X,那么目标就是在线段 CD 上找一点Y,使|XYI/R+IYDI/Q小,这是一个单峰函数。三分套三分就可以了,这是计算几何中的常见题型。

2)整数三分

算法模板

while(right-left >2){     //2或其他数
    int mid1=left+(right - left)/3;    //三等分,1/3处
    int mid2=right-(right - left)/3;    //三等分,2/3处
    if(check(mid1)> check(mid2))
        ...    //移动right
    else
        ...    //移动left
}

注意:第一行的right-left>2,如果写成right>left,当right-left<3时会陷入死循环

三 题目练习

函数

题目描述

给定n 个二次函数f(a),(a),..., fn(a) (均形如 aa’ + ba + c),设F() =max(fi(a),f2(a),..., n(c),求F(a)在区间 0,1000] 上的最小值
输入格式
输入第一行为正整数工,表示有工组数据
每组数据第一行一个正整数n,接着n 行,每行3个整数 a,b,c,用来表示每个二次函数的3个系数,注意二次函数有可能退化成一次。
输出格式
每组数据输出一行,表示 F()的在区间 0,1000] 上的最小值。答案精确到小数点后四位,四舍五入。

样例:

输入

2
1
2 0 0
2
2 0 0
2 -4 2

输出

0.0000
0.5000

题目分析

主要考了一点关于函数的知识罢,题目大意是给你一堆二次函数,F(x)定义为对于每一个x取每一个函数对应的y的最大值,题目是求F[x]在一定区间中的最小值。

因为同时考虑100个函数有些过于困难,我决定先从简单的两个函数开始

 我们可以看到,这里函数的最小值很容易找见,同时我们关注到整个函数是一个下凸函数我们知道,开口向上的二次函数是下凸函数,那么假使两人下凸函数取最大值还是下凸函数,就说明题目给的F(X)是一个下凸函数,我们就可以用三分法来寻找最值。
换而言之,本题的难点在于
已知f(x),g(a)为下凸函数,证明h(a) = ma((a),g(a))是一个下凸函数
证明如下
对于任意的0 < a < 1
总有f(ax1 +(1 - a)2) < af(a1) + (1 - a)f(a2) < ah(a1) + (1 - a)h(2)
同理,对于g(a)也有相似的结论
那么很容易推出
h(ax1 + (1 - a)a2) = max(f(ax1 + (1 - a)2),g(ax1 + (1 - a)a2)) < ah(al) + (1 -a)h(x2)
这就证明了h(x)是一个凸函数
那么我们只需要在上面跑个三分求最值就ok了。

题目解答

#include<stdio.h>
#include<math.h>
int T;
int n;
int a[100010],b[100010],c[100010];
//已知f(x),g(x)为下凸函数,
//则h(x)=max(f(x),g(x))是一个下凸函数。
//h(x)=max(f(x),g(x)...)
double f(double x)					//计算某一点的h(x) 
{
	double ans=0;
	int i;
	for(i=1;i<=n;i++)
	ans=fmax(ans,a[i]*1.0*x*x+b[i]*1.0*x+c[i]);
	return ans;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		int i;
		scanf("%d",&n);
		for(i=1;i<=n;i++)
		scanf("%d %d %d",&a[i],&b[i],&c[i]);
		double l=0,r=1000;
		while(fabs(r-l)>1e-9)				//三分 
		{
			double mid=l+(r-l)/2;
			if(f(mid-1e-9)>f(mid))	l=mid;
			else		r=mid;
		}
		printf("%.4lf\n",f(l));
	}
}

附录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/98551.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3D激光里程计其四:点云线面特征提取

3D激光里程计其四&#xff1a;点云线面特征提取1. 点云线面特征提取1.1 按线数分割1.2 计算曲率1.3 按曲率大小筛选特征点2. 基于线面特征的位姿变化2.1 帧间关联2.1.1 点云位姿转换2.1.2 线特征关联2.1.3 面特征关联2.2 残差函数2.2.1 线特征2.2.2 面特征2.3 位姿优化2.3.1 线…

数据结构——二叉树2.0

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;数据结构——二叉树 &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 ☂️<4>开发环境&#xff1a;Visual Studio 2022 &#x1f4ac;<5>前言&#xff1a;上期讲了…

尚医通-医院接口设置(七)

&#xff08;1&#xff09;后台系统-医院设置接口-需求和准备 &#xff08;2&#xff09;后台系统-医院设置接口-创建基础类 &#xff08;3&#xff09;医院设置接口-查询和逻辑删除 &#xff08;4&#xff09;医院的设置接口-统一返回结果定义 &#xff08;5&#xff09;医…

[附源码]Python计算机毕业设计Django校园代取快递系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

知到/智慧树——大学生心理健康(华东政法大学)参考答案

目录 注&#xff1a;有些图片上传异常&#xff0c;请以参考答案为准&#xff0c;不要以蓝色选项为全部答案。 第一章测试 第二章测试 第三章测试 第四章测试 第五章测试 第六章测试 第七章测试 第八章测试 第九章测试 第十章测试 第十一章测试 第十二章测试 第一章…

传统技术如何阻碍零信任以及如何应对

随着组织采用零信任安全模型&#xff0c;传统技术制造了一些障碍。事实上&#xff0c;根据最近的一项研究&#xff0c;更换或重建现有的遗留基础设施是实施零信任的最大挑战。 通用动力公司的 2022 年零信任研究报告对美国联邦、民事和国防机构的 300 名 IT 和项目经理进行了调…

计算机毕设Python+Vue兴澜幼儿园管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

重定向和缓冲区

文章目录一个奇怪的现象缓冲区详解如何理解缓冲区缓冲区是谁给我提供的&#xff1f;缓冲区的源码体现案例&#xff1a;模拟实现FILE结构体第二个奇怪的现象重定向命令行上使用重定向操作dup2系统调用接口stdout和stderror一个奇怪的现象 首先&#xff0c;我们来看这样一段代码…

毕业设计 - 基于Java的聊天室系统设计与实现【源码+论文】

文章目录前言一、项目设计1. 模块设计服务器模块设计客户端模块设计2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 java 设计项目: 基于Java聊天室系统的设计与实现 一、项目设计 1. 模块设计 服务器模块设计 服务端的功能主要如下&#xff1a; 一&#xf…

R语言绘制森林图

在绘制森林图之前当然需要先下载RStudio软件啦&#xff0c;在下载后需要安装对应的rtool,最后将两者关联起来才能使用其中对应的包&#xff0c;否则只安装了软件很多功能不能使用而且还会报错&#xff0c;这篇文章主要是总结怎么使用forestploter包绘制森林图&#xff0c;本来是…

【Linux修炼手册:基本指令(完结)】

Life is about waiting for the right moment to act. 目录 1 zip/unzip指令 2 tar指令&#xff08;重要&#xff09;&#xff1a;打包/解包&#xff0c;不打开它&#xff0c;直接看内容 3 bc指令 4 uname –r指令 5 重要的几个热键[Tab],[ctrl]-c, [ctrl]-d 6 shutdown 7…

智能语音之远场关键词识别实践(二)

上篇&#xff08;智能语音之远场关键词识别实践&#xff08;一&#xff09;&#xff09;讲了“远场关键词识别”项目中后端上的实践。本篇将讲在前端上的一些实践以及将前端和后端连起来形成一个完整的方案。下图是其框图&#xff1a;&#xff08;麦克风阵列为圆阵且有四个麦克…

SpringMVC【学习笔记】

SpringMVC是什么? Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web 框架&#xff0c;即使用了MVC架构模式的思想&#xff0c;将web 层进行职责解耦&#xff0c;基于请求驱动指的就是使用请求-响应模型&#xff0c;框架的目的就是帮助我们简化…

看2022年卡塔尔世界杯有感

一、我印象中第一次看世界杯是2010年南非世界杯 自己第一次踢球是什么时候已经记不清了&#xff0c;大概是小学时候。因为我印象中第一次看世界杯是2010年南非世界杯&#xff0c;因为世界杯主题曲也比较好听&#xff0c;当然&#xff0c;我认为1998年法国世界杯的主题曲最为经…

Python中的魔法方法

python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两个下划线包围来命名的 Python的魔法方法&#xff0c;也称为dunder(双下划线)方法。大多数的时候&#xff0c;我们将它们用于简单的事情&#xff0c;例如构造函数(init)、字符串表示(str&#xff0c; r…

计算机毕设Python+Vue兴发农家乐服务管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux | 套接字(socket)编程 | UDP协议讲解

文章目录TCP与UDP的区别网络字节序套接字接口介绍sockaddr结构服务端UDP套接字设置客户端UDP套接字设置TCP与UDP的区别 TCPUDP传输层协议传输层协议有连接无连接可靠连接不可靠连接面向字节流面向数据报 首先&#xff0c;网络通信模型是分层的&#xff0c;模型的每一层都有属于…

深入jvm字节码

深入jvm字节码1.深入剖析class文件结构1.1初探class文件1.2 class文件结构解析1.2.1 魔数1.2.2 版本号1.2.3 常量池1.2.4 Access flags1.2.5 this_class,super_name,interfaces1.2.6 字段表1.2.7 方法表1.2.8 属性表1.3使用javap查看类文件2.字节码基础2.1字节码概述2.2java虚拟…

一文看懂---B树及其简单实现

目录 1.B树的引入 2.B树的概念 3.B树是如何插入的&#xff1f; 4.具体的代码实现 1.B树的引入 在以往我们在内存中搜索数据时&#xff0c;可以使用红黑树&#xff0c;平衡树&#xff0c;哈希表等数据结构&#xff0c;但是当数据量比较大&#xff0c;不能一次放进内存&…

[附源码]计算机毕业设计Python仓储综合管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…