• 最近点对问题 POJ 3714 Raid && HDOJ 1007 Quoit Design


    题意:有n个点,问其中某一对点的距离最小是多少

    分析:分治法解决问题:先按照x坐标排序,求解(left, mid)和(mid+1, right)范围的最小值,然后类似区间合并,分离mid左右的点也求最小值

    POJ 3714

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    const int N = 1e5 + 5;
    const double INF = 1e100;
    struct Point {
        double x, y;
        bool flag;
        bool operator < (const Point &rhs) const {
            return x < rhs.x;
        }
    };
    Point point[N*2];
    int idy[N*2];
    int n;
    
    bool cmp_y(int i, int j) {
        return point[i].y < point[j].y;
    }
    
    double squ(double x) {
        return x * x;
    }
    
    double get_dist(Point &a, Point &b) {
        if (a.flag == b.flag) {
            return INF;
        }
        return sqrt (squ (a.x - b.x) + squ (a.y - b.y));
    }
    
    double min_dist(int left, int right) {
        if (left == right) {
            return INF;
        }
        else if (right - left == 1) {
            return get_dist (point[left], point[right]);
        } else {
            int mid = left + right >> 1;
            double ret = std::min (min_dist (left, mid), min_dist (mid + 1, right));
            if (ret == 0) {
                return ret;
            }
            int endy = 0;
            for (int i=mid; i>=left&&point[mid].x-point[i].x<=ret; --i) {
                idy[endy++] = i;
            }
            for (int i=mid+1; i<=right&&point[i].x-point[mid+1].x<=ret; ++i) {
                idy[endy++] = i;
            }
            std::sort (idy, idy+endy, cmp_y);
            for (int i=0; i<endy; ++i) {
                for (int j=i+1; j<endy&&point[j].y-point[i].y<ret; ++j) {
                    ret = std::min (ret, get_dist (point[i], point[j]));
                }
            }
            return ret;
        }
    }
    
    int main() {
        int T; scanf ("%d", &T);
        while (T--) {
            scanf ("%d", &n);
            for (int i=0; i<2*n; ++i) {
                scanf ("%lf%lf", &point[i].x, &point[i].y);
                if (i < n) {
                    point[i].flag = false;
                } else {
                    point[i].flag = true;
                }
            }
            std::sort (point, point+2*n);
            printf ("%.3f
    ", min_dist (0, 2 * n - 1));
        }
    
        return 0;
    }

    HDOJ 1007

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    const int N = 1e5 + 5;
    const double INF = 1e100;
    struct Point {
        double x, y;
    };
    Point point[N], py[N];
    int n;
    
    bool cmp_x(const Point &a, const Point &b) {
        return a.x < b.x;
    }
    bool cmp_y(const Point &a, const Point &b) {
        return a.y < b.y;
    }
    
    double squ(double x) {
        return x * x;
    }
    
    double get_dist(Point &a, Point &b) {
        return sqrt (squ (a.x - b.x) + squ (a.y - b.y));
    }
    
    double min_dist(int left, int right) {
        if (left + 1 == right) {
            return get_dist (point[left], point[right]);
        } else if (left + 2 == right) {
            return std::min (get_dist (point[left], point[left+1]), 
                    std::min (get_dist (point[left], point[right]), get_dist (point[left+1], point[right])));
        } else {
            int mid = left + right >> 1;
            double ret = std::min (min_dist (left, mid), min_dist (mid + 1, right));
            int cnt = 0;
            for (int i=mid; i>=left&&point[mid].x-point[i].x<=ret; --i) {
                py[cnt++] = point[i];
            }
            for (int i=mid+1; i<=right&&point[i].x-point[mid+1].x<=ret; ++i) {
                py[cnt++] = point[i];
            }
            std::sort (py, py+cnt, cmp_y);
            for (int i=0; i<cnt; ++i) {
                for (int j=i+1; j<cnt&&py[j].y-py[i].y<ret; ++j) {
                    ret = std::min (ret, get_dist (py[i], py[j]));
                }
            }
            return ret;
        }
    }
    
    int main() {
        while (scanf ("%d", &n) == 1) {
            if (!n) {
                break;
            }
            for (int i=0; i<n; ++i) {
                scanf ("%lf%lf", &point[i].x, &point[i].y);
            }
            std::sort (point, point+n, cmp_x);
            printf ("%.2f
    ", min_dist (0, n - 1) / 2);
        }
    
        return 0;
    }
    

      

  • 相关阅读:
    基于Lucene/XML的站内全文检索解决方案
    内容管理系统(CMS)的设计和选型
    Lucene入门与使用[转]
    为自己的系统搞个全文搜索 参考值:2 (转)
    C# 时间函数
    Lucene倒排索引原理(转)
    什么是内容管理系统CMS?
    网络测试常用命令
    C#与C的区别
    人生致命的八个经典问题
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5340775.html
Copyright © 2020-2023  润新知