hdu1007_平面最近点对模板

n^2的算法绝壁炸

自我感觉nlogn的算法——分治+简单优化

1、将点集按照先x较小优先,再y较小优先排序,求得区间(left, mid), (mid+1, right)中的最近点对的距离,则dis = 两者的较小值

2、枚举left到right的点对,如果fabs(p[mid].x-p[i].x) <= dis, 则将其加入tmpp[]点集,然后按照y较小优先排序tmpp

3、两个循环枚举tmpp点集,如果tmpp[j].y-tmpp[i].y >= dis,则可以退出第二个循环, 求出两点的最小距离更新dis

4、返回dis

*****************************************************************************************************************************************************************************************************

#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int maxn = 1e5 + 10;
const double INF = 1e20;

typedef struct
{
    double x, y;
}point;

point p[maxn], tmpp[maxn];

bool cmpxy(point a, point b)
{
    if(a.x != b.x) return a.x < b.x;
    return a.y < b.y;
}

bool cmpy(point a, point b)
{
    return a.y < b.y;
}

double getdis(point a, point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double close_pair(int l, int r);

int main()
{
    int n;
    while(scanf("%d", &n), n)
    {
        for(int i = 1; i <= n; ++i)
            scanf("%lf %lf", &p[i].x, &p[i].y);
        sort(p+1, p+n+1, cmpxy);
        double ans = close_pair(1, n) * 0.5;
        printf("%.2f\n", ans);
    }
    return 0;
}

double close_pair(int l, int r)
{
    double dis = INF;
    if(l == r) return dis;
    if(l + 1 == r) return getdis(p[l], p[r]);
    int mid = (l + r) >> 1;
    double d1 = close_pair(l, mid);
    double d2 = close_pair(mid+1, r);
    dis = min(d1, d2);
    int cnt = 0;
    for(int i = l; i < r; ++i)
        if(fabs(p[mid].x-p[i].x) <= dis)
            tmpp[++cnt] = p[i];
    sort(tmpp+1, tmpp+cnt+1, cmpy);
    for(int i = 1; i <= cnt; ++i)
        for(int j = i+1; j <= cnt; ++j)
        {
            if(tmpp[j].y-tmpp[i].y >= dis)
                break;
            dis = min(dis, getdis(tmpp[i], tmpp[j]));
        }
    return dis;
}


猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/80139091
今日推荐