先甩地址:杭电1007
题目大意:
第一行给出点的个数n,第二行开始到第n+1行给出n个点的坐标,然后求出点的最近距离的1/2
题目思路:
穷举法是肯定不行的,时间复杂度会很高。这里寻找最近点对用的是分治的思路。
贴代码:
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define min(a, b) a>b?b:a
struct Point
{
double x;
double y;
int n;
};
int L = -1, R = 1;
Point a[100001];
Point b[100001];
bool cmp(Point a, Point b)
{
if(a.x == b.x) return a.y < b.y;
else return a.x < b.x;
}
bool cmp2(Point a, Point b)
{
if(a.y == b.y) return a.x < b.x;
else return a.y < b.y;
}
double Distance(Point flag1, Point flag2)
{
return sqrt(pow(flag1.x - flag2.x, 2.0) + pow(flag1.y - flag2.y, 2.0));
}
double fenzhi(int first, int last)
{
double d;
int num = last - first;
if(num == 0) return 0;
else if(num == 1) d = Distance(a[first], a[last]);
else if(num == 2)
{
double t1, t2, t3;
t1 = Distance(a[first], a[first+1]);
t2 = Distance(a[first+1], a[last]);
t3 = Distance(a[first], a[last]);
d = min(t1, t2);
d = min(d, t3);
}
else
{
double leftmin, rightmin, minp;
int mid = (first + last)/2, p = 0, i, j;
leftmin = fenzhi(first, mid);
rightmin = fenzhi(mid+1, last);
d = min(leftmin, rightmin);
for(i=first; i<=mid; ++i)
{
double leftpoint = a[mid].x - d;
if(a[i].x >= leftpoint)
{
b[p].n = L;
b[p].x = a[i].x;
b[p].y = a[i].y;
++p;
}
}
for(; i<=last; ++i)
{
double rightpoint = a[mid].x + d;
if(a[i].x <= rightpoint)
{
b[p].n = R;
b[p].x = a[i].x;
b[p].y = a[i].y;
++p;
}
}
sort(b, b+p, cmp2);
for(i=0; i<p; ++i)
{
for(j=1; (j<=7)&&(i+j<p); ++j)
{
if(b[i].n != b[i+j].n)
{
minp = Distance(b[i], b[i+j]);
if(minp < d)
d = minp;
}
}
}
}
return d;
}
int main()
{
int n;
while(scanf("%d", &n)!=EOF && n>0)
{
double result = 0;
for(int i=0; i<n; ++i)
{
scanf("%lf %lf", &a[i].x, &a[i].y);
a[i].n = 0;
}
sort(a, a+n, cmp);
result = fenzhi(0, n-1);
printf("%.2lf\n", result/2);
}
return 0;
}
注意点:
1.穷举法会超时
2.复杂公式另开函数,我在这出错好几次QAQ
(纯吐槽:3.注意scanf里面数据的类型,别和我一样的脑抽QAQ)