UVA 10245 The Closest Pair Problem (分治法)

题目原文:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1186

Given a set of points in a two dimensional space, you will have to find the distance between the closest two points.
Input The input file contains several sets of input. Each set of input starts with an integer N(0 ≤ N ≤ 10000), which denotes the number of points in this set. The next N line contains the coordinates of N twodimensional points. The first of the two numbers denotes the X-coordinate and the latter denotes the Y -coordinate. The input is terminated by a set whose N = 0. This set should not be processed. The value of the coordinates will be less than 40000 and non-negative.
Output
For each set of input produce a single line of output containing a floating point number (with four digits after the decimal point) which denotes the distance between the closest two points. If there is no such two points in the input whose distance is less than 10000, print the line ‘INFINITY’.


题目大意:10000个点,求最近的两点之间的距离。多组数据。

解题思路:因为数据量太大,如果采用枚举的办法肯定超时,所以采用分治法的策略,每次将所有点按照x坐标排序,然后从中分成两边,每边再递归下去计算自己内部的最小值,最后再借助这个最小值作为约束条件,判断一些距离中间轴不超过当前最小值的点之间的距离。因为有当前最小值的束缚,所以每个点需要考虑的点的范围并不大。http://blog.csdn.net/zhang20072844/article/details/6776386 这篇文章中有相关的证明。

AC代码:

/*
    @Author: wchhlbt
    @Date:   2017/3/1
*/
#include <bits/stdc++.h>

#define Fori(x) for(int i=0;i<x;i++)
#define Forj(x) for(int j=0;j<x;j++)
#define maxn 10005
#define inf 0x3f3f3f3f
#define ONES(x) __builtin_popcount(x)
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<double, double> P;

const double eps =1e-8;
const int mod = 1000000007;
const double PI = acos(-1.0);

int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

P a[maxn];
int impossible = inf;
double ans;
bool cmp(P r,P s)
{
    return r.second<s.second;
}
double solve(P *a, int n)
{
    if(n<=1)
        return inf;
    int m = n/2;
    double d = min(solve(a,m),solve(a+m,n-m));
    double x = a[m].first;//划分线
    //inplace_merge(a,a+m,a+n,cmp);//对两个有序的数列归并排序
    sort(a,a+n,cmp);//将所有点按照y排序,也可以使用上面的归并排序
    vector<P> b;
    for(int i = 0; i<n; i++){
        if(fabs(a[i].first-x)>=d) continue;//距离中间轴超过d,可以跳过
        for(int j = b.size()-1; j>=0; j--){
            double dx = a[i].first - b[j].first;
            double dy = a[i].second - b[j].second;
            if(dy-d>=eps)//y值相差超过d也可以跳过
                break;
            d = min(d,sqrt(dx*dx + dy*dy));
        }
        b.push_back(a[i]);
    }
    return d;
}
int main()
{
    //cin>>n;
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(4);
    int n;
    while(cin>>n && n){
        for(int i = 0; i<n; i++){
            cin>>a[i].first>>a[i].second;
        }
        sort(a,a+n);
        double ans = solve(a,n);
        if(ans-1e4>=eps)
            cout << "INFINITY" << endl;
        else
            cout << ans << endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值