zoukankan      html  css  js  c++  java
  • 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; 
    } 
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    22. Generate Parentheses (backTracking)
    21. Merge Two Sorted Lists
    20. Valid Parentheses (Stack)
    19. Remove Nth Node From End of List
    18. 4Sum (通用算法 nSum)
    17. Letter Combinations of a Phone Number (backtracking)
    LeetCode SQL: Combine Two Tables
    LeetCode SQL:Employees Earning More Than Their Managers
  • 原文地址:https://www.cnblogs.com/beisong/p/4440788.html
Copyright © 2011-2022 走看看