原题:http://acm.hdu.edu.cn/showproblem.php?pid=1007
条件:
多组测试数据,n个点(2<=n<=100000),接下来输入n行点对,求点对之间距离的最小值的一半,保留两位小数。
解题思路:
以x坐标和y坐标分别进行归并排序,当x值相等时,以y值小的在前,当y值相等也是相似。
解题代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#define MAX 2147483647
using namespace std;
double c[100005][2];
void MergeSort(double a[][2],int left,int middle,int right,double c[][2])
{
int x=left,x1=middle+1;
int y=middle,y1=right,k=0;
while(x<=y&&x1<=y1)
{
if(a[x][0]<a[x1][0])
{
c[k][0]=a[x][0];
c[k++][1]=a[x++][1];
}
else if(a[x][0]==a[x1][0])
{
if(a[x][1]<=a[x1][1])
{
c[k][0]=a[x][0];
c[k++][1]=a[x++][1];
}
else
{
c[k][0]=a[x1][0];
c[k++][1]=a[x1++][1];
}
}
else
{
c[k][0]=a[x1][0];
c[k++][1]=a[x1++][1];
}
}
while(x<=y)
{
c[k][0]=a[x][0];
c[k++][1]=a[x++][1];
}
while(x1<=y1)
{
c[k][0]=a[x1][0];
c[k++][1]=a[x1++][1];
}
for(int i=0;i<k;i++)
{
a[left+i][0]=c[i][0];
a[left+i][1]=c[i][1];
}
}
void SplitArray(double a[][2],int left,int right,double c[][2])
{
if(left<right)
{
int middle=(left+right)/2;
SplitArray(a,left,middle,c);
SplitArray(a,middle+1,right,c);
MergeSort(a,left,middle,right,c);
}
}
void MergeSort1(double a[][2],int left,int middle,int right,double c[][2])
{
int x=left,x1=middle+1;
int y=middle,y1=right,k=0;
while(x<=y&&x1<=y1)
{
if(a[x][1]<a[x1][1])
{
c[k][0]=a[x][0];
c[k++][1]=a[x++][1];
}
else if(a[x][1]==a[x1][1])
{
if(a[x][0]<=a[x1][0])
{
c[k][0]=a[x][0];
c[k++][1]=a[x++][1];
}
else
{
c[k][0]=a[x1][0];
c[k++][1]=a[x1++][1];
}
}
else
{
c[k][0]=a[x1][0];
c[k++][1]=a[x1++][1];
}
}
while(x<=y)
{
c[k][0]=a[x][0];
c[k++][1]=a[x++][1];
}
while(x1<=y1)
{
c[k][0]=a[x1][0];
c[k++][1]=a[x1++][1];
}
for(int i=0;i<k;i++)
{
a[left+i][0]=c[i][0];
a[left+i][1]=c[i][1];
}
}
void SplitArray1(double a[][2],int left,int right,double c[][2])
{
if(left<right)
{
int middle=(left+right)/2;
SplitArray1(a,left,middle,c);
SplitArray1(a,middle+1,right,c);
MergeSort1(a,left,middle,right,c);
}
}
int main()
{
int n,x,y;
double a[100005][2],min1=MAX,min2=MAX;
while(scanf("%d",&n)!=EOF&&n!=0)
{
min1=MAX;
min2=MAX;
for(int i=0;i<n;i++)
scanf("%lf%lf",&a[i][0],&a[i][1]);
SplitArray(a,0,n-1,c);
for(int i=0;i<n-1;i++)
{
int j=i+1;
while(true&&j!=n)
{
min1=min(min1,pow(abs(a[i][0]-a[j][0]),2)+pow(abs(a[i][1]-a[j][1]),2));
if(a[j][0]!=a[j+1][0]||a[i][0]==a[j][0])
break;
else
j++;
}
}
SplitArray1(a,0,n-1,c);
for(int i=0;i<n-1;i++)
{
int j=i+1;
while(true&&j!=n)
{
double ans=pow(abs(a[i][0]-a[j][0]),2)+pow(abs(a[i][1]-a[j][1]),2);
min2=min(min2,ans);
if(a[j][1]!=a[j+1][1]||a[i][1]==a[j][1])
break;
else
j++;
}
}
min1=min(min1,min2);
min1=sqrt(min1)/2;
printf("%.2lf\n",min1);
}
return 0;
}