HDU 1007 最近点对

本文详细介绍了分治法求最近点对的算法原理及实现过程,包括递归分割点集、计算最短距离、处理边界情况等关键步骤,并通过实例展示了算法的应用。此外,还指出了常见错误及其解决办法。

分治法求最近点对

递归将点不断分成小组,计算最短距离。此时的最短距离仅仅是两点都属两块的某一块(这里的分割点是mid点)。

还需要考虑两点分属两块的情况。这时对于选点则把范围缩小到了以mid为中心。再将距离mid点x轴2*mindist范围点考虑在内。在这些点中,再取mid点,留下那些

y的距离不大于middist 的点进行距离计算。


PS:刚开始min函数写错了,写成了max,一直tle.使用max则会导致选取的点越来越多。TLE则就不奇怪了。

对于使用递归方法实现分治,其实质使用了小范围内得到的结果会缩小整体范围内的搜索空间。递归函数要有范围参数噢。

递归的直观理解可以是1 2 3 等简单情况完后得到的结果返回,组拼全局解。

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn=100005;
int n;
struct P
{
    double x,y;
}p[maxn],ans[maxn];
double min(double a,double b){return a<b?a:b;}
bool cmpx(struct P a,struct P b){return a.x<b.x;}
bool cmpy(struct P a,struct P b){return a.y<b.y;}
double dist(struct P a,struct P b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
double solve(int l,int r)
{
    if(l+1==r)
        return (dist(p[l],p[r]));
        else if(l+2==r)
            return min(dist(p[l],p[l+1]),min(dist(p[l+1],p[r]),dist(p[r],p[l])) );
    int mid=(l+r)>>1;
    double res=min(solve(l,mid),solve(mid+1,r));//这里避免了==mid 的情况
    int cnt=0,i,j;
    for(i=l;i<=r;i++)
    {
        if(fabs(p[i].x-p[mid].x)<=res)
            ans[cnt++]=p[i];
    }
    sort(ans,ans+cnt,cmpy);
    for( i=0;i<cnt;i++)
        for( j=i+1;j<cnt;j++)
    {
        if(ans[j].y-ans[i].y>=res) break;
        res=min(res,dist(ans[i],ans[j]));
    }
    return res;
}
int main()
{
    while(scanf("%d",&n),n)
    {
        int i;
        for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);//输入点
        sort(p,p+n,cmpx);//按x排序
        double res=solve(0,n-1);
        printf("%.2lf\n",res/2);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值