• poj3714 Raid


    哈,就这样水过去了??

    不科学呀。

    好吧,平面最近点对(伪)。

    就是一个二分的事:

    1.以x排序。

    2.二分,递归求解。

    具体来讲,主要难在如何求 横跨两个区域的最近点对 这一环节。

    那么是这样做的:首先我们会有个ans是左右的最小值对吧。

    我们只考虑在划分线左右两边不超过ans的那些点(即为[_l, _r])

    然后把这些点暴力求解即可AC按照y排序,这样的情况下,再只考虑与一个点上下不超过ans的那些点即可......

    那么下面是我的暴力版写法:

     1 /// poj 3714
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 using namespace std;
     7 typedef long long LL;
     8 const int N = 100010;
     9 const double INF = (double)(0x7f7f7f7f);
    10 
    11 struct Point {
    12     LL x, y;
    13     bool f;
    14     bool operator < (const Point &k) const {
    15         return x < k.x;
    16     }
    17 }p[N << 1];
    18 
    19 inline double dis(int i, int j) {
    20     return sqrt((double)((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y)));
    21 }
    22 
    23 double twsolve(int l, int r) {
    24     if(l == r) return INF;
    25     int mid = (l + r) >> 1;
    26     double k = min(twsolve(l, mid), twsolve(mid + 1, r));
    27     int _l, _r;
    28     for(_l = mid; _l >= l; _l--) {
    29         if(p[_l].x <= p[mid + 1].x - k) {
    30             break;
    31         }
    32     }
    33     for(_r = mid + 1; _r <= r; _r++){
    34         if(p[_r].x >= p[mid].x + k) {
    35             break;
    36         }
    37     }
    38     if(_l < l) _l = l;
    39     if(_r > r) _r = r;
    40     double ans = k;
    41     for(int i = _l; i <= mid; i++) {
    42         for(int j = mid + 1; j <= _r; j++) {
    43             if(!(p[i].f ^ p[j].f)) continue;
    44             ans = min(ans, dis(i, j));
    45         }
    46     }
    47     return ans;
    48 }
    49 
    50 int main() {
    51     int T, n;
    52     scanf("%d", &T);
    53     while(T--) {
    54         scanf("%d", &n);
    55         for(int i = 1; i <= n; i++) {
    56             scanf("%I64d %I64d", &p[i].x, &p[i].y);
    57             p[i].f = 0;
    58 
    59         }
    60         for(int i = 1; i <= n; i++) {
    61             scanf("%I64d %I64d", &p[i + n].x, &p[i + n].y);
    62             p[i + n].f = 1;
    63         }
    64         sort(p + 1, p + (n << 1) + 1);
    65         printf("%.3lf
    ", twsolve(1, n << 1));
    66         //cout << twsolve(1, n << 1) << endl;
    67     }
    68     return 0;
    69 }
    AC代码

    附赠数据生成器:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<ctime>
     4 using namespace std;
     5 int main()
     6 {
     7     freopen("in.in","w",stdout);
     8     srand(time(0));
     9     printf("1
    ");
    10     int n = rand() % 100000 + 1;
    11     printf("%d
    ", n);
    12     n = n << 1;
    13     for(int i = 1; i <= n; i++) {
    14         printf("%d %d
    ", rand() % 1000010 + 1, rand() % 1000010 + 1);
    15     }
    16     return 0;
    17 }
    数据生成器

    [update]2018.10.20

    这回写的是正规的nlogn,洛谷P1429 平面最近点对

    y的排序使用归并,少一个排序的log。

    然后发现一点小问题:我写的错误的程序A了,但是正确的却WA了......以后写了对的正解再发上来吧。

  • 相关阅读:
    BUAA_OO_2020_Unit3_Overview
    BUAA_OS_2020_Lab2_Code_Review
    BUAA_OO_2020_Unit2_Overview
    BUAA_OS_2020_Lab1_Code_Review
    BUAA_OO_2020_Unit1_Overview
    实验十 团队作业6:团队项目用户验收&Beta冲刺
    【Beta】Scrum meeting 4
    【Beta】Scrum meeting 3
    【Beta】Scrum meeting 2
    【Beta】Scrum meeting 1
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9029793.html
Copyright © 2020-2023  润新知