HDU 1007 二维最近点对问题 / 分治

来源:互联网 发布:sony smartband 知乎 编辑:程序博客网 时间:2024/05/22 00:43

发现两两比较的问题都可以用分治办法解决~~~

很多排序都这样~~

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);}}


0 0
原创粉丝点击