• hdu 1007 Quoit Design, 平面最近点对


    平面最近点对的经典做法就是分治。所有点先按x再按y排序,然后取中间位置的点,利用其x坐标值将点划分成左右两部分,分别求出两侧的最近点对(设其距离为δ),然后合并。参看下面的图片(来自guyulongcs的专栏,http://blog.csdn.net/guyulongcs/article/details/6841550)合并的时候需要注意,大致有两种做法,一种是把分界线两侧δ范围内的点分别加进一个数组,然后对右侧数组按y坐标值排序,之后依次为每个左侧数组中的点,在右侧数组中寻找与其y坐标值最近的6个点,并计算距离;另一种做法是,将分界线两侧δ范围内的点全部加进一个数组,然后按y坐标排序,每个点与其后面的8个点作比较,求出最近距离。理论上第一种方法更快一些,此处给出第一种 方法实现的代码:

    图片来源:http://images.cnblogs.com/cnblogs_com/king1302217/%E5%88%86%E6%B2%BB%E5%88%92%E5%88%86_1.jpg

    方法1代码:

    #include  <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    #define N 100100
    struct point{
        double x, y;
        bool operator < (const point &a) const{
            if(x == a.x) return y < a.y;
            return x < a.x;
        }
    }p[N], pl[N], pr[N];
    
    bool compy(point a, point b){
        return a.y < b.y;
    }
    
    double dist(point a, point b)
    {
        double x = a.x-b.x, y = a.y-b.y;
        return x*x+y*y;
    }
    int fd(int l, int r, int key)
    {
        while(l < r-1)
        {
            int mid = l+r>>1;
            if(pr[mid].y < key) l = mid+1;
            else r = mid;
        }
        return l;
    }
    
    double solve(int l, int r)
    {
        if(l == r) return 1.0*inf;
        else if(l+1 == r) return dist(p[l], p[r]);
        int mid = l+r>>1;
        double d1 = solve(l, mid);
        double d2 = solve(mid+1, r);
        double d = min(d1, d2);
        int cl = 0, cr = 0;
        for(int i = l; i <= mid; i++)
            if(p[mid].x - p[i].x <= d)
                pl[cl++] = p[i];
        for(int i = mid+1; i <= r; i++)
            if(p[i].x - p[mid].x <= d)
                pr[cr++] = p[i];
        sort(pr, pr+cr, compy); 
        for(int i = 0; i < cl; i++)
        {
            int id = fd(0,cr-1, pl[i].y-d);
            for(int j = 0; j < 6 && id+j < cr; j++)
                d = min(d, dist(pl[i], pr[id+j]));
        }
        return d;
    }
    int main()
    {
        int n;
        while(~scanf("%d", &n), n)
        {
            for(int i = 0; i < n; i++) scanf("%lf %lf", &p[i].x, &p[i].y);
            sort(p, p+n);
            double ans = solve(0, n-1);
            printf("%.2lf
    ", sqrt(ans)/2.0);
        }
        return 0; 
    } 
  • 相关阅读:
    洛谷 P1396 营救(二分答案)
    洛谷 P1807 最长路(toposort)
    洛谷 P1137 旅行计划(toposort)
    [bzoj3032][TYVJ P1924]七夕祭(环形均分纸牌,货仓选址)
    BZOJ3043 IncDec Sequence (差分)
    BZOJ2200 道路与航线(dijk+拓扑排序)
    P1462 通往奥格瑞玛的道路(二分+dijkstra)
    P1020 导弹拦截 O(nlogn)做法
    背包整理(01背包,完全背包,多重背包,分组背包)(待更新)
    [模板]树链剖分
  • 原文地址:https://www.cnblogs.com/beisong/p/4440788.html
Copyright © 2020-2023  润新知