zoukankan      html  css  js  c++  java
  • UVa 10245

      题目大意:给出平面上的n个点,找出距离最近的两个点。

      由于n的取值比较大(n<10000),考虑使用分治法。大概就是把平面上的点分成两部分,分别处理左半部分L、右半部分R以及跨越分界线M的点对,分别求得左半部分内点的最近距离lmin和右半部分的最近距离rmin,令d=min(lmin, rmin),然后处理跨越分界线的点对,由于只需考虑比距离比d值小的点对,所以我们只考察点的x坐标在[M-d, M+d]范围内的点,找出其中的最短距离并更新即可。

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <algorithm>
     4 using namespace std;
     5 #define MAXN 10000+10
     6 
     7 struct Point
     8 {
     9     double x, y;
    10 };
    11 Point point[MAXN], tmp[MAXN];
    12 
    13 bool cmp1(const Point& a, const Point& b)
    14 {
    15     if (a.x != b.x)  return a.x < b.x;
    16     return a.y < b.y;
    17 }
    18 
    19 bool cmp2(const Point& a, const Point& b)
    20 {
    21     if (a.y != b.y)  return a.y < b.y;
    22     return a.x < b.x;
    23 }
    24 
    25 double dis(const Point& a, const Point& b)
    26 {
    27     double t1 = (a.x - b.x) * (a.x - b.x);
    28     double t2 = (a.y - b.y) * (a.y - b.y);
    29     return sqrt(t1+t2);
    30 }
    31 
    32 double conquer(int left, int right)
    33 {
    34     if (left == right)  return 10010;
    35     if (right - left == 1)  return dis(point[left], point[right]);
    36     int mid = (left + right) / 2;
    37     double left_min = conquer(left, mid);
    38     double right_min = conquer(mid+1, right);
    39     double d = min(left_min, right_min);
    40     int cnt = 0;
    41     for (int i = left; i <= right; i++)
    42         if (fabs(point[i].x-point[mid].x) < d)
    43             tmp[cnt++] = point[i];
    44     sort(tmp, tmp+cnt, cmp2);
    45     for (int i = 0; i < cnt; i++)
    46         for (int j = i+1; j < i+7 && j < cnt; j++)
    47         {
    48             double t = dis(tmp[i], tmp[j]);
    49             if (t < d)  d = t;
    50         }
    51     return d;
    52 }
    53 
    54 int main()
    55 {
    56 #ifdef LOCAL
    57     freopen("in", "r", stdin);
    58 #endif
    59     int n;
    60     while (scanf("%d", &n) != EOF && n)
    61     {
    62         for (int i = 0; i < n; i++)
    63             scanf("%lf%lf", &point[i].x, &point[i].y);
    64         sort(point, point+n, cmp1);
    65         double ans = conquer(0, n-1);
    66         if (ans > 10000)  printf("INFINITY
    ");
    67         else  printf("%.4lf
    ", ans);
    68     }
    69     return 0;
    70 }
    View Code

      关于在考察跨越分界线的点对时所作的优化,可参考这里

  • 相关阅读:
    表达式计算 java 后缀表达式
    动态规划略有所得 数字三角形(POJ1163)
    SharedPreferences的基本数据写入和读取
    安卓 io流 写入文件,再读取的基本使用
    SqLite的基本使用
    安卓手机开机开启指定Activity
    Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK fla
    广播的基本使用,判断是否有可用网络,并弹出设置窗口
    AsyncTask下载网络图片的简单应用
    Intellij_idea-14官方快捷键中文版
  • 原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3279764.html
Copyright © 2011-2022 走看看