发现两两比较的问题都可以用分治办法解决~~~
很多排序都这样~~
HDU 1007
http://acm.hdu.edu.cn/showproblem.php?pid=1007
问题描述:
找到最小的圆半径,使得每次套中的玩具只能是一个。
就是找最近点对的距离,再除2 ;
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
struct Point{
double x , y ;
}p[100005];
int arr[100005];
bool cmpX(const Point& a,const Point& b)
{
return a.x < b.x ;
}
bool cmpY(const int& a,const int& b)
{
return p[a].y < p[b].y ;
}
double dis(int a,int b)
{
return sqrt((p[a].x - p[b].x)*(p[a].x - p[b].x) + (p[a].y - p[b].y)*(p[a].y - p[b].y));
}
double abs(double a,double b)
{
return (a - b > 0) ? (a - b):(b - a);
}
double find(int l ,int r)
{
if(l+1 == r)return dis(l , r);
if(l + 2 == r)return min(dis(l , r) , min(dis(l+1,r) , dis(l , l+1)));
int mid = (l + r) >> 1 ;
double ans = min(find(l , mid),find(mid+1 ,r)); // 分治
int cnt = 0 ;
for(int i = l;i <= r;i++)
{
if(abs(p[i].x , p[mid].x) <= ans)
arr[cnt++] = i ; //记录中间的点
}
sort(arr , arr + cnt , cmpY);
for(int i = 0;i < cnt - 1;i++)
for(int j = i + 1;j < cnt;j++)
{
double d = dis(arr[i] , arr[j]);
if(d >= ans)break;
ans = min(ans , d);
}
return ans ;
}
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 , cmpX);
printf("%.2lf\n",find(0, n-1)/2);
}
}