求出纯左边和纯右边的最小值。
下面我们要考虑横跨两边的点的最小值会不会比这个最小值还要小。
假设我们纯的最小值为x。
我们从mid点开始向两边扩展
往左扩展,l=mid,l到mid的x坐标之差小于最小值,我们l--,直到扩展到x坐标之差都大于最小值位置。
同理r=mid向右扩展。
为什么用x坐标之差呢,因为三角形,如果短边都大于了,那么斜边肯定会大于最小值。
最后我们获得一个l到r的区域,这个区域内的点与mid的x坐标之差都小于最小值,而直接距离不一定。
我们双重for枚举单个判断即可。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
typedef struct nodep
{
double x,y;
}point;
point P[10004];
bool cmp( point a, point b )
{
return a.x < b.x;
}
double dist( point a, point b )
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double mindist( int a, int b )
{
if ( a > b ) return 40004;
int l = (a+b)/2,r = (a+b)/2,mid = (a+b)/2;
double d = min( mindist( a, mid-1 ), mindist( mid+1, b ) );
while ( l >= a && d > P[mid].x-P[l].x ) l --;
while ( r <= b && d > P[r].x-P[mid].x ) r ++;
for ( int i = l+1 ; i < r ; ++ i )
for ( int j = i+1 ; j < r ; ++ j )
d = min(d,dist(P[i],P[j]));
return d;
}
int main()
{
int n;
while ( ~scanf("%d",&n) && n ) {
for ( int i = 0 ; i < n ; ++ i )
scanf("%lf%lf",&P[i].x,&P[i].y);
sort( P, P+n, cmp );
double d = mindist( 0, n-1 );
if ( d >= 10000 )
printf("INFINITY\n");
else printf("%.4lf\n",d);
}
return 0;
}