题目 :http://acm.hdu.edu.cn/showproblem.php?pid=3124
算法 : 排序加枚举
思路 :将圆用左端点排序, 然后考虑与当前圆一定范围内的圆,求最小距离即可。算暴力方法,最快时间为5秒。枚举时我们认为只有距当前点一定距离的圆才会影响最短距离。
正常的算法:利用扫描线和平衡二叉树,目前只会,还理论没有实现。
代码
#include <stdio.h>
#include <math.h>
#define MAXN 51100
struct NODE{
double x, y, r;
};
NODE rely[MAXN];
int N;
void Qsort(int l, int r){
int ll = l, rr = r;
double mid = rely[(r - l) / 2 + l].x - rely[(r - l) / 2 + l].r;
NODE temp;
while(ll < rr){
while(rely[ll].x - rely[ll].r < mid) ll ++;
while(rely[rr].x - rely[rr].r > mid) rr --;
if(ll <= rr){
temp = rely[ll];
rely[ll] = rely[rr];
rely[rr] = temp;
ll ++, rr --;
}
}
if(ll < r) Qsort(ll, r);
if(l < rr) Qsort(l, rr);
}
doubleGet_len(int i, int j){
double dx = rely[i].x - rely[j].x, dy = rely[i].y - rely[j].y;
return (sqrt(dx * dx + dy * dy) - rely[i].r - rely[j].r);
}
doubleGet_ANS(int n){
int i, j;
double min = 10000000.0, d;
for(i = 0; i < n - 1; i ++)
for(j = i + 1; j < i + 2500 && j < n; j ++)
if(min > (d = Get_len(i, j))) min = d;
return min;
}
int main(){
int CASE, i;
scanf("%d", &CASE);
while(CASE --){
scanf("%d", &N);
for(i = 0; i < N; i ++)
scanf("%lf %lf %lf", &rely[i].x, &rely[i].y, &rely[i].r);
Qsort(0, N - 1);
printf("%.6lf\n", Get_ANS(N));
}
return 0;
}