实质:最近点对问题、时间复杂度为O(nlognlogn)
問題の説明
あなたは遊び場で輪投げを演じたことがありますか?輪投げはフラットリングが授与囲まれ、すべてのおもちゃで、いくつかのおもちゃで投げされているゲームです。
Cybergroundの分野では、各おもちゃの位置が固定されており、そしてそれは一度に一つのおもちゃを囲むことができるようにリングを慎重に設計されています。一方、ゲームをより魅力的に見えるように、リングが最大の半径を有するように設計されています。フィールドの構成を考えると、あなたは、このようなリングの半径を見つけることになっています。
すべてのおもちゃは、平面上の点であることを前提としています。点とリングの中心間の距離は、リングの半径よりも厳密に小さい場合、点は、リングに囲まれています。2つのおもちゃが同じ点に配置されている場合は、リングの半径が0であると考えられます。
入力
入力は、いくつかのテストケースで構成されています。各場合について、最初の行は整数Nを含み(2 <= N <= 100,000)、フィールド内の玩具の総数。次いで、Nラインは、各玩具の座標である(X、Y)の対を含有する、従います。入力は、N = 0で終了します。
出力
各テストケースについては、一列に小数点以下2桁まで正確Cybergroundマネージャによって必要とされるリングの半径を印刷します。
サンプル入力
2
0 0
1 1
2
1 1
1 1
3
-1.5 0
0 0
0 1.5
0
サンプル出力
0.71
0.00
0.75
#include <iostreamの> する#include <cstdioを> する#include <CStringの> する#include <cmath> の#include <アルゴリズム> 使用して 名前空間STDを、 constの ダブル INF = 1E20; const int型 N = 100005 ; 構造体のポイント { ダブルX。 ダブルY; } [N]を指します。 int型のn; INT TMPT [N]。 BOOL cmpxy(constのポイント&、constのポイント&B) { 場合(斧!=BX) リターン斧< BX。 返す AYを< ことで、 } ブール cmpy(CONSTの INTと、CONSTの INT&B) { 戻り点[A] .Y < ポイント〔B〕.Y。 } ダブル分(ダブル、ダブルB) { 戻り <bは?A:B; } 二重 DIS(int型 I、INT J) { 戻り SQRT((点[I] .X点[J] .X)*(点[I] .x- 点[J] .X) +(点[I] .Y点[J] .Y)*(点[I] .y- 点[J] .Y))。 } 二重 Closest_Pair(int型左を、int型右) { ダブル D = INF。 もし(==左右) リターンD; 場合(左+ 1 ==は右) を返すDISを(左、右)。 int型半ば=(左+右)>> 1 。 ダブル D1 = Closest_Pair(左、中)。 二重 D2 = Closest_Pair(MID + 1 、右)。 D = 分(D1、D2)。 int型 I、J、K = 0 ; // 分离出宽度为D的区间 用(=左I; iは=右<; iは++ ) { 場合(ファブ(点[中間] .X点[i]は.X)<= D) TMPT [K ++ ] = I。 } ソート(TMPT、TMPT + K、cmpy)。 // 线性扫描 用(i = 0 iは++; I <K ) { ため(J = I + 1、J <K &&点のyポイント[j]をTMPT] Y <D [i]をTMPT]。 J ++ ) { ダブル D3 = DIS(TMPT [I]、[J])TMPT。 もし(D> D3) D = D3。 } } 戻りD。 } int型のmain() { 一方(真) { scanf関数(" %のD "、&N) もし(nは== 0 ) ブレーク。 以下のために(int型 i = 0 ; iがn <I ++の) のscanf(" %のLFの%のLF "、&ポイント[I] .X、&ポイントを[I] .Y)。 ソート(点、点 + N、cmpxy)。 printf("%.2lf \ n "、Closest_Pair(0、N- 1)/ 2 ); } 戻り 0 ; }