这道题目数据是不是还是弱了?(分治思路)
查看原帖
这道题目数据是不是还是弱了?(分治思路)
419173
hiro653楼主2022/10/23 20:10

先贴上经过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排序之后再进行比较吧

2022/10/23 20:10
加载中...