三分

在这里插入图片描述
根据题目,在一个二维坐标中,我们要输入N个点坐标,而在x轴(-10000,10000)这个区间存在无数个点,我们假设它为x1,x2,x3…这些点中,每个点到我们输入的N个点的距离存在一个最大值,我们要在这些最大值中找到最小的那一个然后输出。
那么,思路是什么呢?
既然存在这样一个点,那么我们就要找到它所在的那个区间。但是,这里要注意了,是最小值,有最值,而且是最小值,那么就可以用三分法,那为什么不用二分法呢?因为二分法是对与单调区间的,(这在高中大家接触二分法的时候举得例子就是单调函数吧,我记得好像是单调且端点异号。)而三分法是针对有峰值的函数的。显然,在本题中,用三分法是更加方便快捷的。其实,二分法也可以用,就是对分下来的每一个区间进行再次二分。我觉得要用到递归好像。二分法比较复杂一点。后面我掌握后一定会及时向大家分享的。
下面,我们就来介绍一下三分法的解题步骤:
1.首先,我们要将先分为两半,然后在对其中的一变进行再分两半,总体就是2:1:1的形式。这里,我们用mid表示一半,用midmid表示一半的一半。

double check(double x){
    double max=0;
    for(int i=0;i<n;i++){
        double temp=sqrt(a[i].y*a[i].y+(a[i].x-x)*(a[i].x-x));
        if(temp>max)  max=temp;
    }
    return max;
}

我们就是将在x轴坐标的某个点,到所有的N个点的最大值求出并且返回。

double thsearch(double l,double r)
{
    double mid,midmid;
    for(int i=0;i<100;i++){
        mid=l+(r-l)/2;
        midmid=mid+(r-mid)/2;
        if(check(mid)>check(midmid))l=mid;
        else r=midmid;
    }
    return mid;
}

我们先搞清楚这个循环,对于这个循环有人可能会问了?为什么是100,其他可不可以,答案是:可以,我们先讲讲这个原理,每一次循环,都将剩余的区间进行了又一次的三分,这都是2的负次幂级的下降。所以,大家可以想想,2的-100次幂再乘以区间长度的值应该是足够精确的了。其实也可以50,30等。但博主试了一下,好像3也是可以过的,emmm,这就要看测试数据本身了,我们为了保险起见,还是将值设大一点。
然后,对于循环语句块,首先,mid我们代表的是区间中点,而midmid有代表的是区间中点的中点。那这里可能又有人要问了,为什么将midmid放在中点左边呢?其实,你要想,也可以放在中点的右边,只是将代码进行一些细微的修改罢了,更有甚者,还可以两边都来个for循环,emmm,只是,没有必要!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double pi=acos(-1),eps=1e-10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int n;
struct node{
    int x,y;
}lg[100010];

bool cmp(node a,node b)
{
    return a.x<b.x;
}
double check(double x)
{
    double maxx=0;
    for(int i=0;i<n;i++){
        double tmp=sqrt((lg[i].x-x)*(lg[i].x-x)+lg[i].y*lg[i].y);
        //cout<<tmp<<endl;
        if(tmp>maxx)maxx=tmp;
    }
    return maxx;
}
double thsearch(double l,double r)
{
    double mid,midmid;
    for(int i=0;i<100;i++){
        mid=l+(r-l)/2;
        midmid=mid+(r-mid)/2;
        if(check(mid)>check(midmid))l=mid;
        else r=midmid;
    }
    return mid;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)cin>>lg[i].x>>lg[i].y;
    //sort(lg,lg+n,cmp);
    //double l=lg[0].x,r=lg[n-1].x;
    double max=thsearch(-10000,10000);
    printf("%.4f\n",check(max));

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值