HDU1007 Quoit Design

题目链接

题意不用多说,求平面最近点对的,很简单……我又是一大堆的板子往上面一放,代码就比较长

最近点对,就是分治的方法来求,一半一半地分下去,同时找到x最近的一些点,然后合并的时候枚举比刚刚求到的距离范围内的点,然后求y,整个复杂度应该湿nlogn级别的……还是该理解理解然后脱离板子。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int maxn = (int)1e5 + 10;
const double eps = 1e-8;
int cmp(double x){
	if (fabs(x) < eps) return 0;
	if (x > 0) return 1;
	return -1;
}
inline double sqr(double x){
	return x * x;
}
struct point{
	double x, y;
	point(){}
	point(double a, double b) : x(a), y(b){}
	void input(){
		scanf("%lf%lf", &x, &y);
	}
	friend point operator + (const point &a, const point &b){
		return point(a.x + b.x, a.y + b.y);
	}
	friend point operator - (const point &a, const point &b){
		return point(a.x - b.x, a.y - b.y);
	}
	friend bool operator == (const point &a, const point &b){
		return cmp(a.x - b.x) == 0 && cmp(a.y - b.y) == 0;
	}
	friend point operator * (const double &a, const point &b){
		return point(a * b.x, a * b.y);
	}
	friend point operator / (const point &a, const double &b){
		return point(a.x / b, a.y / b);
	}
	double norm(){
		return sqrt(sqr(x) + sqr(y));
	}
};
double det(const point &a, const point &b){
	return a.x * b.y - a.y * b.x;
}
double dot(const point &a, const point &b){
	return a.x * b.x + a.y * b.y;
}
double dist(const point &a, const point &b){
	return (a - b).norm();
}
point rotate_point(const point &p, double A){
	double tx = p.x, ty = p.y;
	return point(tx * cos(A) - ty * sin(A), tx * sin(A) + ty * cos(A));
}
point a[maxn];
int n, s[maxn];
bool cmpx(int i, int j){
	return cmp(a[i].x - a[j].x) < 0;
}
bool cmpy(int i, int j){
	return cmp(a[i].y - a[j].y) < 0;
}
double min_dist(point a[], int s[], int l, int r){
	double ans = 1e100;
	if (r - l < 20){
		for (int q = l; q < r; q++)
			for (int w = q + 1; w < r; w++)
				ans = min(ans, (a[s[q]] - a[s[w]]).norm());
		return ans;
	}
	int tl, tr, m = (l + r) >> 1;
	ans = min(min_dist(a, s, l, m), min_dist(a, s, m, r));
	for (tl = l; a[s[tl]].x < a[s[m]].x - ans; tl++);
	for (tr = r - l; a[s[tr]].x > a[s[m]].x + ans; tr--);
	sort(s + tl, s + tr, cmpy);
	for (int q = tl; q < tr; q++)
		for (int w = q + 1; w < min(tr, q + 6); w++)
			ans = min(ans, (a[s[q]] - a[s[w]]).norm());
	sort(s + tl, s + tr, cmpx);
	return ans;
}
double Min_Dist(point a[], int s[], int n){
	for (int i = 0; i < n; i++)
		s[i] = i;
	sort(s, s + n, cmpx);
	return min_dist(a, s, 0, n);
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("in", "rt", stdin);
	#endif
	while(scanf("%d", &n) == 1 && n){
		for (int i = 0; i < n; i++)
			a[i].input();
		memset(s, 0, sizeof(s));
		double ans = Min_Dist(a, s, n);
		printf("%.2lf\n", ans / 2.0);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值