这道题目数据是不是还是弱了?(分治思路)

P1429 平面最近点对(加强版)

hiro653 @ 2022-10-23 20:10:00

先贴上经过O2优化后AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
struct node {

    double x, y;
}nodes[200010];

node nodes2[200010];

bool cmpx(node a, node b) {

    return a.x < b.x;
}

bool cmpy(node a, node b) {

    return a.y < b.y;
}

double dac(int l,int r) {

    if (l == r) return 1e9;
    else if (r == l + 1) return pow(pow(nodes[l].x - nodes[r].x, 2) + pow(nodes[l].y - nodes[r].y, 2), 0.5);
    else {

        int mid = l + r >> 1;
        //中线两边距离
        double min_wid = min(dac(l, mid), dac(mid + 1, r));
        double RtoL_min = min_wid;
        double mid_line = (nodes[mid].x + nodes[mid + 1].x) / 2.0;
        //找到左右两边在中线附近min_wid内部的点
        int l1 = -1, r1 = -1;
        for (int i = l;i <= mid;i++) {

            if (mid_line - nodes[i].x <= min_wid) {

                l1 = i;
                break;
            }
        }
        for (int i = r;i >= mid+1;i--) {

            if (nodes[i].x- mid_line <=  min_wid) {

                r1 = i;
                break;
            }
        }
        //O(14n)
        if (l1 != -1 && r1 != -1) {

            //对两条个边界内部的点按y坐标排序

            //sort(nodes + l1, nodes + r1+1, cmpy);
            //只检查|i-j|<=7内部的点
            for (int i = l1;i <= r1;i++) {

                int l2 = max(i - 7, l1);
                int r2 = min(i + 7, r1);
                for (int j = l2;j <= r2;j++) {

                    if (i != j&&abs(nodes[i].x-nodes[j].x)<RtoL_min) {

                        double tmp = pow(pow(nodes[i].x - nodes[j].x, 2) + pow(nodes[i].y - nodes[j].y, 2), 0.5);
                        RtoL_min = min(RtoL_min, tmp);
                    }
                }
            }
            return RtoL_min;
        }

        return min_wid;

    }
}

int main() {

    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) {

        scanf("%lf %lf",&nodes[i].x,&nodes[i].y);
        //nodes2[i].x = nodes[i].x;
        //nodes2[i].y = nodes[i].y;
    }
    sort(nodes + 1, nodes + n + 1, cmpx);
    //sort(nodes2 + 1, nodes2 + n + 1, cmpx);
    printf("%.4f", dac(1, n));

}

可以看到在合并左右两边时,只是把位于中线区间内按x大小排序后的附近7个点进行了比较,但事实上应该把这部分点先按照y排序之后再进行比较吧


by VividCycle @ 2022-10-23 20:11:56

@hiro653 还有一个加强加强版啊。


|