HDU-1007 Quoit Design(分治求平面内最近两点间距离)

题目连接

题意:

        找到平面内,最近两个点间距离, 最后答案除以2

数据范围:

        N (2 <= N <= 100,000) N 个点,

思路:

         如果暴力解法O(n^{2})必然是 10^{^{10}}  所以应该有 O(n{log_{2}}^{n})算法。

         O(n{log_{2}}^{n})树,分治,等等,这题应该用分治算法。

        1)既然用分治,就应该吧问题分成几份,先分两份试试。(为什么分治算法能优化呢 1 )分解问题时是树形结构。一分为2 一分为3.....。2)子问题单独求解后向上合并,可以扔掉一些不需要比较的点)。

        2)按照 点的 横坐标 x 排序 (当然可以y),然后找到中间的点,把问题一分为2个子问题,然后继续找到左边区间 距离最近的 两点找到,右边区间  距离最近的两点。比较大小,然后合并左右区间,

        3) 但是还有可能的是最近点对中的两点分属这两个集合.。所以我们需要再算一些点,

        4)那我们合并是应该算那些点呢?求出两个子问题的解后,还没有合并(ans = 两个子问题中  两点最近的值),然后合并后我们应该从合并后的区间中线找到 距离中线水平距离不超过 ans 的点,(要是距离中线点得水平距离都超过 ans了,那我们肯定不用),然后把这些点再放到一个数组内进行求解,求出距离小于 ans 的点.

扫描二维码关注公众号,回复: 10715636 查看本文章

       5)优化:如果两个之间y轴间的距离大于ans那我们也不再比较,这样最后合并之后得出的一部后按照y点排序,减少比较次数。

AC:

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<algorithm>
using namespace std;
const double esp = 1e-8;
#define Equ(a, b) (fabs((a) - (b)) < (eps))
#define Less(a, b) ((a) - (b) < (-esp))    //a < b 
const int maxn = 100005;
struct type {
    double x, y;
} point[maxn];
bool cmp_x(type a, type b) {
    return a.x < b.x;
} 
bool cmp_y(type a, type b) {
    return a.y < b.y;
}
double dis (type a, type b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double solve (int left, int right) {
    if(right - left == 1) return dis(point[left], point[right]);    //只有两点 
    else if(right - left == 2) {    //有3个点 
        double minn = min(dis(point[left], point[right]), dis(point[left+1], point[right]));
        minn = min(minn, dis(point[left], point[left+1]));
        return minn;
    }else {//3个点以上 
        int mid = (left + right) >> 1;
        double ans = min(solve(left, mid), solve(mid + 1, right));
        int cnt = 0;
        vector<type> P;
        for(int i = left; i <= right; ++i) {
            if(abs(point[i].x - point[mid].x) <= ans)
                P.push_back(point[i]);
        }
        sort(P.begin(), P.end(), cmp_y);
        for(int i = 0; i < P.size(); ++i) {
            for(int j = i + 1; j < P.size(); ++j) {
                if(P[j].y - P[i].y > ans) break;
                ans = min(ans, dis(P[i], P[j]));
            }
        }
        return ans;    
    }
}
int main() {
    int N;
    while(scanf("%d", &N) && N){
        for(int i = 0; i < N; ++i) {
            scanf("%lf %lf",&point[i].x, &point[i].y);
        }
        sort(point, point + N, cmp_x);
        printf("%.2lf\n", solve(0,N-1)/2);
    }
    return 0;
} 
发布了199 篇原创文章 · 获赞 156 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Harington/article/details/105110392