参考资料:
给定一个单峰函数,如何求得极值点?
对于区间 [ l , r ] [l, r] [l,r],求出两个三等分点 l s e c lsec lsec和 r s e c rsec rsec,然后比较这两个点的函数值 f ( l s e c ) f(lsec) f(lsec)和 f ( r s e c ) f(rsec) f(rsec)。如果有 f ( r s e c ) > f ( l s e c ) f(rsec)>f(lsec) f(rsec)>f(lsec),说明极值点一定在区间 [ l s e c , r ] [lsec, r] [lsec,r]内取得,因为如果答案在区间 [ l , l s e c ) [l,lsec) [l,lsec)内取得,则一定有函数 f f f在区间 [ l r e c , r ] [lrec, r] [lrec,r]内单调递减,于是有 f ( l s e c ) > f ( r s e c ) f(lsec)>f(rsec) f(lsec)>f(rsec),这与 f ( r s e c ) > f ( l s e c ) f(rsec)>f(lsec) f(rsec)>f(lsec)相矛盾。
不难发现,上述做法在每次循环中会让区间长度变为原长度的 2 / 3 2/3 2/3。我们还可以取区间中点两边附近的两个点,这样可以让在每次循环后让区间长度变为原长度的 1 / 2 1/2 1/2。
// eps = 1e-7
while(r-l>1e-6){
double mid = (l+r)/2;
double midl = mid-eps, midr = mid+eps;
if(f(midr)>f(midl)) l = midl, ans = mid;
else r = midr;
}
循环条件最好为最大轮数。
在求解多项式函数的值时往往需要采用秦九韶算法。
//N为多项式的最高次,数组a[]按次数从高到低存储
double f(double x){
double res = 0;
for(int i=0;i<=N;i++) res = res*x + a[i];
return res;
}