zoukankan      html  css  js  c++  java
  • 最近点对问题学习笔记

    最近点对问题学习笔记

    最近点对问题,就是在一个点集中找到最近的一对点的距离。

    先看一道例题

    AcWing119

    在题解的帮助下,我终于A了此题。

    题目大意就是有n个特工和n个核电站,求最近的任意一个特工到任意一个核电站的距离。

    首先我们只要将点分为两组,同组的点之间距离为无穷大,就可以将本题转换为最近点对问题。

    最近点对问题如何解呢?

    第一时间想到的是n2的暴力,但无疑是要超时的。

    于是我们需要用分治来优化一下。

    首先在一般情况下,最近两个点的横坐标的差是较小的,我们可以对于横坐标进行分治。

     

    如图,以横坐标为第一关键字排序后,将所有点分成两部分(至于中间那个随便分到哪块)。

    很显然最短距离是在左块的最短距离和右块的最短距离,当然也可能不同块的点的距离,比如说图中的ab。

    前两种都是非常方便实现的,只需要不断分治就好。麻烦的是第三种情况。

    我们可以先将前两种的最小值ans求出,以横坐标和中间点差小于等于ans的才可能是第三种情况。

    于是我们只需要求这些点之中最短距离。

    对于这些点我们可以直接用暴力做,一般情况下应该不会很大。

    当然,如果纵坐标的距离大于ans,也是不可能是最短距离的。

        	sort(b + 1, b + cnt + 1, cmp2);
    	rep(i, 1, cnt)
    		rep(j, i + 1, cnt){
    			if(b[j].y >= b[i].y + ans) break;
    			ans = min(ans, dist(b[i], b[j]));
    		}
    

     可以将纵坐标为第一关键字排序,进行剪枝。

    放上我错了好几次的代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <vector>
     7 #define rep(x, l, r) for(int x = l; x <= r; x++)
     8 #define repd(x, r, l) for(int x = r; x >= l; x--)
     9 #define clr(x, y) memset(x, y, sizeof(x))
    10 #define all(x) x.begin(), x.end()
    11 #define pb push_back
    12 #define mp make_pair
    13 #define MAXN 200005
    14 #define fi first
    15 #define se second
    16 #define SZ(x) ((int)x.size())
    17 using namespace std;
    18 typedef long long ll;
    19 typedef vector<int> vi;
    20 typedef pair<int, int> pii;
    21 const int INF = 1 << 30;
    22 const int p = 1000000009;
    23 int lowbit(int x){ return x & (-x);}
    24 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
    25 
    26 int n;
    27 struct node{
    28     double x, y;
    29     bool col;
    30 }a[MAXN], b[MAXN];
    31 
    32 bool cmp1(node a, node b){
    33     if(a.x == b.x) return a.y < b.y;
    34     return a.x < b.x;
    35 }
    36 
    37 bool cmp2(node a, node b){
    38     if(a.y == b.y) return a.x < b.x;
    39     return a.y < b.y;
    40 }
    41 
    42 double dist(node a, node b){
    43     if(a.col == b.col) return INF;
    44     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    45 }
    46 
    47 double work(int l, int r){
    48     if(l == r) return INF;
    49     if(l == r - 1) return dist(a[l], a[r]);
    50     int mid = (l + r) >> 1;
    51     double ans = min(work(l, mid), work(mid + 1, r));
    52     int cnt = 0;
    53     rep(i, l, r)
    54         if(a[i].x >= a[mid].x - ans && a[i].x <= a[mid].x + ans) b[++cnt] = a[i];
    55     sort(b + 1, b + cnt + 1, cmp2);
    56     rep(i, 1, cnt)
    57         rep(j, i + 1, cnt){
    58             if(b[j].y >= b[i].y + ans) break;
    59             ans = min(ans, dist(b[i], b[j]));
    60         }
    61     return ans;
    62 }
    63 
    64 int main(){
    65     int t;
    66     scanf("%d", &t);
    67     while(t--){
    68         scanf("%d", &n);
    69         rep(i, 1, n){
    70             scanf("%lf%lf", &a[i].x, &a[i].y);
    71             a[i].col = 0;
    72         }
    73         rep(i, n + 1, 2 * n){
    74             scanf("%lf%lf", &a[i].x, &a[i].y);
    75             a[i].col = 1;
    76         }
    77         n *= 2;
    78         sort(a + 1, a + n + 1, cmp1);
    79         double ans = work(1, n);
    80         printf("%.3f
    ", ans);
    81     }
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    golang 简易聊天
    golang 自定义封包协议(转的)
    PHP 7 测试用例(转)
    android 百度地图开发
    Android studio 签名使用转
    百度ueditor 拖文件或world 里面复制粘贴图片到编辑中 上传到第三方问题
    Android控件属性大全(转)
    Android studio 一个项目中添加两个module遇到的bug
    win7 64位DCOM配置(关于导出excel 配置计算机组件服务)(转)
    Python学习--07迭代器、生成器
  • 原文地址:https://www.cnblogs.com/nblyz2003/p/12147898.html
Copyright © 2011-2022 走看看