• hdu 1007 Quoit Design (Nearest Point Pair)


    http://acm.hdu.edu.cn/showproblem.php?pid=1007

      最近点对。

      做法是先对所有点先按x再按y排序,然后进行分治搜索最近点对。对于每个区间,如果点数小于3,就直接暴力搜索最近点,否则对其进行分治。分治出来的两个区间,我们要挑选出与中点距离小于已找到的最近距离的所有点,然后对他们进行暴力枚举最近距离。根据《算法导论》证明的,合并两个区间之后,被挑选出来的点不会超过6个,于是可以得到总的时间复杂度是O(nlogn)。

    代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 #include <cmath>
     6 
     7 using namespace std;
     8 
     9 const int N = 111111;
    10 const double FINF = 1e100;
    11 
    12 template <class T> T sqr(T x) { return x * x;}
    13 struct Point {
    14     double x, y;
    15     Point() {}
    16     Point(int x, int y) : x(x), y(y) {}
    17     bool operator < (Point a) const {
    18         return x < a.x || x == a.x && y < a.y;
    19     }
    20     Point operator + (Point a) {
    21         return Point(x + a.x, y + a.y);
    22     }
    23 } p[N];
    24 
    25 bool cmpY(int x, int y) { return p[x].y < p[y].y;}
    26 inline double dist(Point x, Point y) { return sqrt(sqr(x.x - y.x) + sqr(x.y - y.y));}
    27 
    28 #define lson l, m
    29 #define rson m + 1, r
    30 
    31 int arr[N];
    32 
    33 double closest(int l, int r) {
    34     if (l >= r) return FINF;
    35     if (l + 1 == r) return dist(p[l], p[r]);
    36     int m = l + r >> 1;
    37     double cd = min(closest(lson), closest(rson));
    38     int end = 0;
    39     for (int i = l; i <= r; i++) {
    40         if (dist(p[i], p[m]) <= cd) {
    41             arr[end++] = i;
    42         }
    43     }
    44     sort(arr, arr + end, cmpY);
    45     for (int i = 0; i < end; i++) {
    46         for (int j = i + 1; j < end; j++) {
    47             cd = min(cd, dist(p[arr[i]], p[arr[j]]));
    48         }
    49     }
    50     return cd;
    51 }
    52 
    53 int main() {
    54 //    freopen("in", "r", stdin);
    55     int n;
    56     while (~scanf("%d", &n) && n) {
    57         for (int i = 0; i < n; i++) {
    58             scanf("%lf%lf", &p[i].x, &p[i].y);
    59         }
    60         sort(p, p + n);
    61         printf("%.2f\n", closest(0, n - 1) / 2.0);
    62     }
    63     return 0;
    64 }
    View Code

    UPD:

      之前的代码估计是水过了,更新一下代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 
     7 using namespace std;
     8 
     9 template<class T> T sqr(T x) { return x * x;}
    10 typedef pair<double, double> Point;
    11 #define x first
    12 #define y second
    13 inline double dist(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
    14 inline bool cmpx(Point a, Point b) { return a.x < b.x;}
    15 inline bool cmpy(Point a, Point b) { return a.y < b.y;}
    16 const int N = 111111;
    17 const double FINF = 1e100;
    18 
    19 #define lson l, m
    20 #define rson m + 1, r
    21 Point pt[N], tmp[N];
    22 
    23 double npp(int l, int r) {
    24     if (r - l <= 3) {
    25         double ret = FINF;
    26         for (int i = l; i < r; i++) {
    27             for (int j = i + 1; j <= r; j++) {
    28                 ret = min(ret, dist(pt[i], pt[j]));
    29             }
    30         }
    31         return ret;
    32     }
    33     int m = l + r >> 1;
    34     Point mid = pt[m];
    35     double md = min(npp(lson), npp(rson));
    36     int tt = 0;
    37     for (int i = l; i <= r; i++) if (fabs(pt[i].x - mid.x) <= md) tmp[tt++] = pt[i];
    38     sort(tmp, tmp + tt, cmpy);
    39     for (int i = 0; i < tt; i++) {
    40         int j = i + 1;
    41         while (j < tt) {
    42             if (tmp[j].y - tmp[i].y > md) break;
    43             md = min(md, dist(tmp[i], tmp[j]));
    44             j++;
    45         }
    46     }
    47     return md;
    48 }
    49 
    50 int main() {
    51     //freopen("in", "r", stdin);
    52     int n;
    53     while (~scanf("%d", &n) && n) {
    54         for (int i = 0; i < n; i++) scanf("%lf%lf", &pt[i].x, &pt[i].y);
    55         sort(pt, pt + n, cmpx);
    56         printf("%.2f\n", npp(0, n - 1) / 2);
    57     }
    58     return 0;
    59 }
    View Code

    ——written by Lyon

  • 相关阅读:
    minimum-path-sum
    pascals-triangle
    Java -- 二分查找
    redis缓存雪崩,击穿,穿透(copy)
    使用redis限制提交次数
    数据库的悲观锁和乐观锁
    mysql常用命令
    php压缩Zip文件和文件打包下载
    php去除数据库的数据空格
    php获取本年、本月、本周时间戳和日期格式的实例代码(分析)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_1007_Lyon.html
Copyright © 2020-2023  润新知