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 还有一个加强加强版啊。