当前位置: 首页 > news >正文

初涉三分法

三分法:大概是一种思想?

何为三分

众所周知,二分可以解决线性函数的极值问题。

那么相应的,三分就是解决凸形/凹形函数的极值问题。

这里有一篇博客讲的不错:二分答案法、三分法

(图自hihocoder)

 

主要的思路就是选定l,r端点,使 lmid = l+(r-l)/3 ; rmid = r-(r-l)/3 ,继而比较f(lmid)和f(rmid)

显而易见的,若在凹形函数中,f(lmid) < f(rmid),那么$[rmid,r]$这一段一定大于最小值,故$r=rmid$;反之亦然。

至于lmid和rmid为$[l,r]$三等分点的原因,是为了尽量使选取的两点相差较大。

 

不过群里有人表示,如果函数值比较难求,可以使用黄金分割比例优化lmid和rmid。因为这样子可以重复利用函数值。

 

三分板子

luoguP3382 【模板】三分法

题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

输出为一行,包含一个实数,即为x的值。四舍五入保留5位小数。


 这个没有什么好说的,直接三分。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const double eps = 0.000001;
 4 int n;
 5 double l,r,dx[15];
 6 double val(double x)
 7 {
 8     double ret = dx[1];
 9     for (int i=2; i<=n+1; i++)
10         ret = (ret*x)+dx[i];
11     return ret;
12 }
13 void three_divide(double l, double r)
14 {
15     while (l+eps < r)
16     {
17         double lmid = l+(r-l)/3;
18         double rmid = r-(r-l)/3;
19         if (val(lmid) > val(rmid))
20             r = rmid;
21         else l = lmid;
22     }
23     printf("%.5f\n",l);
24 }
25 int main()
26 {
27     scanf("%d%lf%lf",&n,&l,&r);
28     for (int i=1; i<=n+1; i++)
29         scanf("%lf",&dx[i]);
30     three_divide(l, r);
31     return 0;
32 }
lg3382

 

 

HDU2899Strange fuction

Problem Description
Now, here is a fuction:
  F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100)
Can you find the minimum value when x is between 0 and 100.
> 现在有一个函数F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100).找到它在[0,100]内的最小值。
Input
The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has only one real numbers Y.(0 < Y <1e10)
Output
Just the minimum value (accurate up to 4 decimal places),when x is between 0 and 100.
> 四舍五入到4位小数

 这个没有讲明是三分,不过我们可以先观察观察,发现F'(x)在[0,+∞)上是一个增函数。

法一:对于F'(x)二分求零点

 1 #include<cstdio>
 2 #include<cmath>
 3 const double eps = 1e-6;
 4 double y,l,r,mid;
 5 int tt;
 6 double dx(double x)
 7 {
 8     return 42*pow(x,6)+48*pow(x,5)+21*pow(x,2)+10*x-y;
 9 }
10 double f(double x)
11 {
12     return 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-y*x;
13 }
14 int main()
15 {
16     scanf("%d",&tt);
17     for (; tt; tt--)
18     {
19         scanf("%lf",&y);
20         l = 0;r = 100;
21         while (l+eps < r)
22         {
23             mid = (l+r)/2;
24             if (dx(mid) > 0)
25                 r = mid;
26             else l = mid;
27         }
28         printf("%.4f\n",f(l));
29     }
30     return 0;
31 }

法二:发现它在[0,100]上是一个凹形函数,故三分

 1 #include<cstdio>
 2 const double eps = 0.000001;
 3 int tt;
 4 double y;
 5 double f(double x)
 6 {
 7     double ret = 6*x*x*x*x*x*x*x+8*x*x*x*x*x*x+7*x*x*x+5*x*x-y*x;
 8     return ret;
 9 }
10 void three_divide(double l, double r)
11 {
12     while (l+eps < r)
13     {
14         double lmid = l+(r-l)/3;
15         double rmid = r-(r-l)/3;
16         if (f(lmid) < f(rmid))
17             r = rmid;
18         else l = lmid;
19     }
20     printf("%.4lf\n",f(l));
21 }
22 int main()
23 {
24     scanf("%d",&tt);
25     for (; tt; tt--)
26     {
27         scanf("%lf",&y);
28         three_divide(0, 100);
29     }
30     return 0;
31 }

 

hiho1142 : 三分·三分求极值

描述

这一次我们就简单一点了,题目在此:

在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d。

输入

第1行:5个整数a,b,c,x,y。前三个数构成抛物线的参数,后两个数x,y表示P点坐标。-200≤a,b,c,x,y≤200

输出

第1行:1个实数d,保留3位小数(四舍五入)


 

这道题就比较有趣了。

容易想到定义函数为P点到抛物线上横坐标为$x_0$的点的距离。那么我们来观察一下这个函数:

由于$a$,$b$,$c$,$x$,$y$都是给定的,这个看上去很复杂的东西就是的形式(并且根号下的多项式必定为非负数)。那么就很显然,$f(x)$可以三分查找最值。

接下去的问题就变成了怎么选取三分的$l$,$r$:

一种无脑方法就是直接一个-INF和一个INF拿来做。

另一种方法是分类讨论:若P点被抛物线围住(同向抛物线开口方向),就在y=a(x)的两根之中寻找(a(x)表示抛物线函数);若P点在抛物线外,就是对称轴和x之间寻找。

 

 1 #include<bits/stdc++.h>
 2 const double eps = 0.000001;
 3 int a,b,c,d,x,y;
 4 double calc(double x)
 5 {
 6     return a*x*x+b*x+c;
 7 }
 8 double f(double xx)
 9 {
10     return sqrt(pow(calc(xx)-y, 2)+(x-xx)*(x-xx));
11 }
12 void three_divide(double l, double r)
13 {
14     while (r-l > eps)
15     {
16         double lmid = l+(r-l)/3;
17         double rmid = r-(r-l)/3;
18         if (f(lmid) < f(rmid))
19             r = rmid;
20         else l = lmid;
21     }
22     printf("%.3f\n",f(l));
23 }
24 int main()
25 {
26     scanf("%d%d%d%d%d",&a,&b,&c,&x,&y);
27     double pl = -b*1.0/(2*a*1.0);
28     double ll = std::min(pl, x*1.0);
29     double rr = std::max(pl, x*1.0);
30     double del = b*b*1.0+4*a*y-4*a*c;
31     if (del >= 0 && ((a > 0 && calc(x) <= y) || (a < 0 && calc(x) >= y)))
32     {
33         ll = (-b-sqrt(del))/(2*a*1.0);
34         rr = (-b+sqrt(del))/(2*a*1.0);
35     }
36     three_divide(ll, rr);
37     return 0;
38 }

 

 

 

 

END

 

转载于:https://www.cnblogs.com/antiquality/p/8795973.html

相关文章:

  • 关于inodes占用100%解决方法
  • 电商系统处理
  • 20154307《网络对抗》Exp4 恶意代码分析
  • Mac下Nginx访问目录,出现403 Forbidden
  • mac 安装 tomcat 配置
  • 聚类算法
  • 20165215 结对编程——四则运算第一周
  • E: 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。...
  • 01 JS基础
  • geth常用指令
  • 信号是如何在光纤中传播的?
  • 解析Json字符串的三种方法
  • Python_字符串处理方法
  • SqlSugar解决SQLite访问的问题:Unable to load DLL 'SQLite.Interop.dll'
  • PL/SQL的安装
  • CSS3 变换
  • CSS相对定位
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • EventListener原理
  • JAVA SE 6 GC调优笔记
  • Leetcode 27 Remove Element
  • mysql_config not found
  • node.js
  • socket.io+express实现聊天室的思考(三)
  • springboot_database项目介绍
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • swift基础之_对象 实例方法 对象方法。
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 翻译:Hystrix - How To Use
  • 机器学习中为什么要做归一化normalization
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 提醒我喝水chrome插件开发指南
  • 跳前端坑前,先看看这个!!
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 协程
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 在weex里面使用chart图表
  • 7行Python代码的人脸识别
  • 从如何停掉 Promise 链说起
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • #define
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (3)llvm ir转换过程
  • (安卓)跳转应用市场APP详情页的方式
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (转)Google的Objective-C编码规范
  • (转载)OpenStack Hacker养成指南
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Micro Framework初体验
  • .NET MVC第三章、三种传值方式
  • .NET 命令行参数包含应用程序路径吗?