洛谷 P3382 【模板】三分法

洛谷 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\n",l);
    return 0;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
06-20 18:18
是不是意味着秋招就完蛋了
花不开柳成荫:如果你是Java,是的
点赞 评论 收藏
分享
秋盈丶:后续:我在宿舍群里和大学同学分享了这事儿,我好兄弟气不过把他挂到某脉上了,10w+阅读量几百条评论,直接干成精品贴子,爽
点赞 评论 收藏
分享
见见123:简历没有啥问题,是这个社会有问题。因为你刚毕业,没有工作经历,现在企业都不要没有工作经历的。社会病了。
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务