hdu1007最近点对(分治)

该博客介绍了如何使用分治思想解决最近点对问题,详细阐述了将n个点按x坐标排序后,通过计算左右两部分的最近距离并进行合并的方法。在合并过程中,重点关注横坐标分布在最近距离范围[x-minDist, x+minDist]内的点对。算法复杂度为O(nlogn),并提到在HDU的题目中,使用scanf代替cin可以避免TLE错误。" 100919261,5809304,强化学习基础:值函数与期望解析,"['强化学习', '动态规划', '期望']
摘要由CSDN通过智能技术生成

这道题《算法导论》和《编程之美》都有详细的讲解

分治思想:先把n个点按x坐标排序,然后求左边n/2个和右边n/2个的最近距离,最后合并。

合并要考虑 最近点对 的其中一个点在左边,另一个在右边的情况。



      如上图,只需考虑[x-minDist,x+minDist]的这段区域minDist*(2*minDist)的矩形区域,这样一个区域最多只有八个点(反推),所以只用搜索按坐标y排序后紧随其后的7个点即可。0和1,2,3,4....;1和2,3,4...

     这里有详细的证明点击打开链接

     总的算法复杂度为O(nlogn)

     hdu上面这道题用cin读取数据TLE了,改为scanf就AC了


#include <iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

const int maxn=100005;
struct Point{
public:
    double x,y;
};
Point v[maxn];
int ind[maxn];
bool cmpx(const Point &p1,const Point &p2){
    return p1.x<p2.x;
}

bool cmpy(int i1,int i2){
    return v[i1].y<v[i2].y;
}

double dis(const Point& p1, const Point& p2){
    return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
double min(double a,double b)
{
  return a<b?a:b;
}
double devide(int l,int r)
{
    if(r==1+l)return dis(v[r],v[l]);
    if(r==2+l)return min(min(dis(v[l],v[l+1]),dis(v[l+1],v[r])),dis(v[l],v[r]));
    int mid=(l+r)/2;
    int c=0;
    double minDis=min(devide(l,mid),devide(mid+1,r));
    for(int i=l;i<=r;++i){
        if(v[i].x<=v[mid].x+minDis&&v[i].x>=v[mid].x-minDis){
            ind[c++]=i;
        }
    }
    sort(ind,ind+c,cmpy);
    for(int i=0;i<c;++i){
        for(int j=i+1;j<c;++j){
            if(v[ind[j]].y-v[ind[i]].y>=minDis)break;
            minDis=min(minDis,dis(v[ind[i]],v[ind[j]]));

        }
    }
    return minDis;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int n;
    while(cin>>n&&n){
        double x,y;
        for(int i=0;i<n;++i){
            scanf("%lf %lf",&v[i].x,&v[i].y);
        }
        sort(v,v+n,cmpx);
        printf("%.2lf%\n",devide(0,n-1)/2);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值