BZOJ 2458: [BeiJing2011]最小三角形 (分治)

分治就是了.

类似于分治找最近/远点对.

CODE

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-13;
const int MAXN = 200005;
const double INF = 1e15;
#define sqr(x) ((x)*(x))
struct Point {
	double x, y;
	Point(){}
	Point(double x, double y):x(x), y(y){}
	inline friend double dist(const Point &A, const Point &B) {
		return sqrt(sqr(A.x-B.x) + sqr(A.y-B.y));
	}
	inline friend double S_tri(const Point &A, const Point &B, const Point &C) {
		return dist(A, B) + dist(A, C) + dist(B, C);
	}
}a[MAXN];
inline bool cmpx(const Point &A, const Point &B) { return A.x < B.x; }
inline bool cmpy(const Point &A, const Point &B) { return A.y < B.y; }
int n;
double solve(int l, int r) {
	if(r-l < 2) return INF;
	if(r-l == 2) return S_tri(a[l], a[l+1], a[l+2]);
	int mid = (l + r) >> 1; double X = a[mid].x;
	double re = min(solve(l, mid-1), solve(mid+1, r));
	int st = l, ed = r;
	while(X-a[st].x > re/2) ++st;
	while(a[ed].x-X > re/2) --ed;
	sort(a + st, a + ed + 1, cmpy);
	for(int i = st; i <= ed; ++i)
		for(int j = i+1; j <= ed; ++j)
			if(dist(a[i], a[j]) + eps > re/2) break; //剪枝必须加
			else for(int k = j+1; k <= ed; ++k)
					if(dist(a[i], a[k]) + eps > re/2) break;
					else re = min(re, S_tri(a[i], a[j], a[k]));
	sort(a + st, a + ed + 1, cmpx);
	return re;
}
int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i)
		scanf("%lf%lf", &a[i].x, &a[i].y);
	sort(a + 1, a + n + 1, cmpx);
	printf("%.6f\n", solve(1, n));
}

posted @ 2019-12-14 14:50  _Ark  阅读(71)  评论(0编辑  收藏  举报