洛谷 P3382 【模板】三分法
思路
这是一道三分的模板题
用于求单峰函数的极值
首先,在函数上标4个点:(x=l,r,mid,mmid)。其中(mmid)是(mid)与(r)的中点。(其实就是把函数三等分了)
然后我们需要通过迭代来缩小范围((while)循环)
如果(f(mid)>f(mmid)),则(mmid)一定在峰的右边。
如果(f(mid)<f(mmid)),则(mid)一定在峰的左边。
证明:
1.我们假设存在(f(mid)>f(mmid))且(mmid)在峰的左边。
由于(f(x))在峰的左边单调递增,且(f(mid)>f(mmid)),所以(mid)在(mmid)的右边。
然而(mmid = frac{mid+rt}{2}),显然(mid)在(mmid)左边。矛盾。
2.我们假设存在(f(mid)<f(mmid))且(mid)在峰的右边。
由于(f(x))在峰的右边单调递减,且(f(mid)<f(mmid)),所以(mid)在(mmid)的右边。
然而(mmid = frac{mid+rt}{2}),显然(mid)在(mmid)左边。矛盾。
那么如何求(f(n))呢
这就需要用到秦九韶公式了,大家可以自行百度,这里就不说了
代码
#include<bits/stdc++.h>
#define db double
#define N 20
using namespace std;
const db eps=1e-6;
int n;
db a[20],l,r,mid,mmid,k;
db f(db x){
db s=0;
for(int i=0;i<=n;i++)s=s*x+a[i];//秦九韶公式,自行百度
return s;
}
int main(){
scanf("%d%lf%lf",&n,&l,&r);
for(int i=0;i<=n;i++){
scanf("%lf",&a[i]);
}
while(r-l>=eps){
k=(r-l)/3.0;
mid=l+k;
mmid=r-k;
if(f(mid)>f(mmid))r=mmid;
else l=mid;
}
printf("%.5lf
",l);
return 0;
}