牛客寒假算法基础集训营5 牛牛战队的训练地(三分)

题目:https://ac.nowcoder.com/acm/contest/3006/B
参考题解:https://ac.nowcoder.com/acm/problem/blogs/201956
三分法参考博客:https://blog.csdn.net/beiyouyu/article/details/7875480?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

这个题目的方法就是对答案三分,接下来详细说一下三分法
我们都知道二分可以求具有单调性的函数中的某个值。
三分法主要用于解决寻找单峰函数的极值,而这个题目我们分析一下范围可以大致得出随着x增大,最大距离是先增后减的。
所以三分的具体方法就是我们要将分为两半,然后在对其中的一变进行再分两半,总体就是2:1:1的形式。这里,我们用m表示一半,用mm表示一半的一半。要求最小值就只需要每次将边界移到大的那一边
那么还有一个问题,查找答案应该循环多少次?如何将它表示出来?

有两种方法:1.直接用for循环一定的次数。
这里用的是100次。因为每一次循环,都将剩余的区间进行了又一次的三分,这都是2的负次幂级的下降。所以,2的-100次幂再乘以区间长度的值应该是足够精确的了。
2.while循环
while (l + EPS < r)
这里的EPS是一个无限小的数,这个很好理解就不再多说。
代码如下:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f;
const int N=100005;
using namespace std;
typedef long long ll;
struct node{
    int x,y;
}a[N];
int n;
double maxn;
double check(double c){
    maxn=0.0;
    for(int i=1;i<=n;i++){
        double sum=a[i].y*a[i].y+(a[i].x-c)*(a[i].x-c);
        maxn=max(maxn,sum);
    }
    return maxn;
}

void slove(double l,double r){
    for(int i=1;i<=100;i++){
        double m=l+(r-l)/2;
        double mm=l+(m-l)/2;
        if(check(mm)>check(m))
            l=mm;
        else
            r=m;
    }
}
int main ()
{
    //freopen("D:\\input.txt", "r", stdin);
    //freopen("D:\\output.txt", "w", stdout);
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d %d",&a[i].x,&a[i].y);
    slove(-10000,10000);
    double ans=sqrt(maxn);
    cout<<ans<<endl;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值