三分学习(解决凸函数or凹函数的极值)
来源:互联网 发布:淘宝访客来源 网址 编辑:程序博客网 时间:2024/05/16 14:33
思想转载自:http://blog.csdn.net/pi9nc/article/details/9666627
如果遇到凸性或凹形函数时,可以用三分查找求那个凸点或凹点。
如图所示,已知左右端点L、R,要求找到白点的位置。
思路:通过不断缩小 [L,R] 的范围,无限逼近白点。
做法:先取 [L,R] 的中点 mid,再取 [mid,R] 的中点 mmid,通过比较 f(mid) 与 f(mmid) 的大小来缩小范围。
当最后 L=R-1 时,再比较下这两个点的值,我们就找到了答案。
1、当 f(mid) > f(mmid) 的时候,我们可以断定 mmid 一定在白点的右边。
反证法:假设 mmid 在白点的左边,则 mid 也一定在白点的左边,又由 f(mid) > f(mmid) 可推出 mmid < mid,与已知矛盾,故假设不成立。
所以,此时可以将 R = mmid 来缩小范围。
2、当 f(mid) < f(mmid) 的时候,我们可以断定 mid 一定在白点的左边。
反证法:假设 mid 在白点的右边,则 mmid 也一定在白点的右边,又由 f(mid) < f(mmid) 可推出 mid > mmid,与已知矛盾,故假设不成立。
同理: 当求凹点的时候,当f(m) > f(mm)的时候 ,L =m;
当f(m) < f(mm) 的时候,R = mm;证明与上面一般;
zoj3203:
题意:
人左右走动,求影子L的最长长度。
思路:求最长的影子长度;
设x为人灯光垂直线的距离,那么有两个边界,一个是当影子刚好射到墙角的时候,即x = h / H * D ,一个是全都投射到墙上的情况即x = D;
这个肯定在中间的某个位置最长,利用calc(x)公式求出最长的长度,calc公式推导如下:
可以得出L= H - D * (H - h)/x +D -x,不过得注意x的起点是从h / H * D 开始的;
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int maxn = 100000 + 10;#define INF 0x7fffffff#define clr(x,y) memset(x,y,sizeof(x))typedef long long ll;#define eps 10e-10double H,h,D;double calc(double x){ return H - D * (H - h)/x +D -x;}int main(){ int Tcase; scanf("%d",&Tcase); while(Tcase --) { scanf("%lf%lf%lf",&H,&h,&D); double l = D - h /H * D,r = D; while(l + eps < r) { double m = (l + r) / 2, mm = (m + r) /2; if(calc(m) < calc(mm)) { l = m; } else { r = mm; } } printf("%.3lf\n",calc(l)); } return 0;}
当然还有数学方法可以解决这个题:
公式为:L = H + D - ((H - h)*D /x + x),你会发现这就是一个双勾函数,只要把这个函数的最小值,L的最大值就能求出来了,双勾函数的性质,对于一个双勾函数: a*x + b / x .(a> 0 && b > 0)
然后判断一下边界取出最小值代入得到最大值。
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int maxn = 100000 + 10;#define INF 0x7fffffff#define clr(x,y) memset(x,y,sizeof(x))typedef long long ll;#define eps 10e-10double H,h,D;double calc(double x){ return H + D - ((H - h)*D /x + x);}int main(){ int Tcase; scanf("%d",&Tcase); while(Tcase --) { scanf("%lf%lf%lf",&H,&h,&D); double xm = sqrt(D*(H - h)); double l = D - h / H * D,r = D; double ans; if(l <= xm && r >= xm) ans = calc(xm); else if(xm < l) ans = calc(l); else ans = calc(r); printf("%.3lf\n",ans); } return 0;}
HDU 2438
题意:已知汽车的长和宽,l和w,以及俩条路的宽为x和y,汽车所处道路宽为x ,问汽车能否顺利转弯?
分析:汽车能否顺利转弯取决于在极限情况下,随着角度的变化,汽车离对面路的距离是否大于等于0
在上图中需要计算转弯过程中h 的最大值是否小于等于y
很明显,随着角度θ的增大,最大高度h先增长后减小,即为凸性函数,可以用三分法来求解
如图中:
这题转载自http://www.cnblogs.com/nanke/archive/2012/02/12/2348041.html
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int maxn = 1000000 + 10;#define INF 0x7fffffff#define clr(x,y) memset(x,y,sizeof(x))typedef long long ll;#define eps 10e-10double x,y,l,w;double calc_h(double angle){ double s = l * cos(angle) + w *sin(angle) - x; return s * tan(angle) + w * cos(angle);}int main(){ while( ~ scanf("%lf%lf%lf%lf",&x,&y,&l,&w)) { double L = 0,R = acos(-1.0)/2; while(L + eps < R) { double m = (L + R) / 2,mm = (m + R)/2; if(calc_h(m) < calc_h(mm)) { L = m; } else R = mm; } double max_h = calc_h(L); if(max_h <= y) { cout << "yes" << endl; } else cout << "no" << endl; } return 0;}
- 三分学习(解决凸函数or凹函数的极值)
- 利用3分法求凸(凹)函数极值
- 三分法(Ternary Search)求解凸(凹)函数的极值问题<方法篇>
- 三分法(Ternary Search)求解凸(凹)函数的极值问题<方法篇>
- 三分法(Ternary Search)求解凸(凹)函数的极值问题<题目篇>
- HDU3714(Error Curves)三分求二次函数的极值
- 凹函数与凸函数
- 凹函数和凸函数
- 湘潭大学 Hurry Up 三分,求凹函数的最小值问题
- 多元函数的极值
- 机器学习中关于判断函数凸或凹以及最优化的问题
- 机器学习中关于判断函数凸或凹以及最优化的问题
- Hdu 2899 - Strange fuction 二分/三分求函数极值点
- 多元函数的极值及条件极值
- 复习笔记(函数的极值)
- #1142 : 三分·三分求极值 ( 三分极值 )
- 上凹还是下凹,叫法相反的凹函数 Concave Upward and Downward
- matlab求极值的函数
- MFC中如何画带实心箭头的直线
- Linux关机命令详解
- (三)集群容错
- 数据集 —— ground truth 数据集
- 页面动态化的基础 —— Tangram
- 三分学习(解决凸函数or凹函数的极值)
- MFC轻松实现对话框标题更改
- Hibernate映射集合属性3__排序用的sort属性
- 566. Reshape the Matrix
- 欢迎使用CSDN-markdown编辑器
- Minimum number of steps java
- session.invalidate()无效的原因
- 如何循序渐进学习Python语言
- OC语言定义属性时,atomic 与 nonatomic的取舍