一、題目描述
In the field of Cyberground, the position of each toy is fixed, and the ring is carefully designed so it can only encircle one toy at a time. On the other hand, to make the game look more attractive, the ring is designed to have the largest radius. Given a configuration of the field, you are supposed to find the radius of such a ring.
Assume that all the toys are points on a plane. A point is encircled by the ring if the distance between the point and the center of the ring is strictly less than the radius of the ring. If two toys are placed at the same point, the radius of the ring is considered to be 0.
二、題目分析
題目要求套圈的最大半徑,而這個套圈每次只能套一個toy。所以,題目轉化爲求平面中最近的兩個toy之間的距離。也就是最近點對的問題。
1,暴力解法
求n個點中最近的兩個點,共C(n, 2)中匹配,時間複雜度O(n^2).
2,分治
1)讀取點橫縱座標數據,並將點按橫座標升序排列。
2)以中間點爲基準,將平面內的點分爲左右兩個部分。此時,最近點對可能出現在左部分、右部分或者一點在左部分,一點在右部分,共三種情況。
3)求出這三部分的最近點對,取最小值。
對於左右部分的最近點對可以遞歸求解,然後取較小值mini。
對於一點在左部分,一點在右部分的情況,可以有下面兩種處理方式。
a、取點集中橫座標與分界線的距離小於mini的點存入p2數組中,對p2數組按縱座標進行排序。計算p2數組中點對的距離,不斷和mini比較。
b、取點集中橫座標與分界線的距離小於mini的點存入pl, pr兩個數組中,在分界線左邊的放在pl中,否則放在pr中。然後在兩個數組中尋找最近點對,和mini比較。
三、AC代碼
a
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0X3F3F3F3F;
struct Point{
double x;
double y;
} p1[100001], p2[100001];
bool cmp_x(Point p1, Point p2) {
return p1.x < p2.x;
}
bool cmp_y(Point p1, Point p2) {
return p1.y < p2.y;
}
double square(double x) {
return x*x;
}
double dist(Point p1, Point p2) {
return sqrt(square(p1.x-p2.x) + square(p1.y-p2.y));
}
double search_nst(int l, int r) {
if(l == r) return INF;
if(l+1 == r) return dist(p1[l], p1[r]);
int mid = (l+r)/2;
double mini = min(search_nst(l, mid), search_nst(mid+1, r));
int k = 0;
for(int i = l; i <= r; i++) {
if(fabs(p1[i].x - p1[mid].x) < mini) p2[k++] = p1[i];
}
sort(p2, p2+k, cmp_y);
for(int i = 0; i < k; i++) {
for(int j = i+1; j < k && (p2[j].y-p2[i].y) < mini; j++) {
if(dist(p2[i], p2[j]) < mini) mini = dist(p2[i], p2[j]);
}
}
return mini;
}
int main() {
int N;
while(cin >> N && N) {
for(int i = 0; i < N; i++) {
cin >> p1[i].x >> p1[i].y;
}
sort(p1, p1+N, cmp_x);
double ans = search_nst(0, N-1);
printf("%.2lf\n", ans/2.0);
}
}
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0X3F3F3F3F;
struct Point{
double x;
double y;
} p1[100001], pl[100001], pr[100001];
bool cmp_x(Point p1, Point p2) {
return p1.x < p2.x;
}
bool cmp_y(Point p1, Point p2) {
return p1.y < p2.y;
}
double square(double x) {
return x*x;
}
double dist(Point p1, Point p2) {
return sqrt(square(p1.x-p2.x) + square(p1.y-p2.y));
}
double search_nst(int l, int r) {
if(l == r) return INF;
if(l+1 == r) return dist(p1[l], p1[r]);
int mid = (l+r)/2;
double mini = min(search_nst(l, mid), search_nst(mid+1, r));
int k1 = 0, k2 = 0;
for(int i = l; i <= r; i++) {
if(fabs(p1[i].x - p1[mid].x) < mini) {
if(p1[i].x -p1[mid].x < 0) pl[k1++] = p1[i];
else pr[k2++] = p1[i];
}
}
for(int i = 0; i < k1; i++) {
for(int j = 0; j < k2; j++) {
double tmpDist = dist(pl[i], pr[j]);
if(tmpDist < mini) mini = tmpDist;
}
}
return mini;
}
int main() {
int N;
while(scanf("%d", &N) != EOF && N) {
for(int i = 0; i < N; i++) {
//cin >> p1[i].x >> p1[i].y;
scanf("%lf%lf", &p1[i].x, &p1[i].y);
}
sort(p1, p1+N, cmp_x);
double ans = search_nst(0, N-1);
printf("%.2lf\n", ans/2.0);
}
}