ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1429 平面最近点对

2022-04-15 01:01:50  阅读:166  来源: 互联网

标签:跨界点 point 距离 最近 平面 区间 P1429 最优 include


感谢所有AC

传送门

思路

       分治能解决这个题目吗?乍一看并不可行,如果把所有点中分,取左部分的最小距离和右部分的最小距离来作为所有点的最小距离,这样的分治策略明显是不正确的,因为这样就忽视了左部分和右部分中的点形成的点对,即一些跨界的距离可能是最短距离。这是分治所遇到的问题,如果能够解决这个问题,那么分治将是一个很好的解法,时间上也是很可观的。

       怎么处理跨界点对?不妨把思路放简单一点,我直接把所有跨界点对的距离求出来,然后用这些距离来更新答案不就ok了?这样的时间复杂度是 n2 的,是否有优化的空间?由于答案出自三个部分,左区间点对,右区间点对,跨界点对。如果在先知道了左右区间点对的最短距离后,似乎可以用剪枝的思想来优化跨界点对的求解。

       假如目前左右区间点对最优解为 len ,那么只要左区间内的点对跟中分线的垂直距离大于等于 len ,那么他就不可能是最优解,右区间同理。这样就筛除了很大数量的点,接下来,把可能是最优解的点存进数组中,然后 n2 地逐个计算距离并更新答案。这样就可以实现最优解的实现了。

代码

#include <iostream>
#include<algorithm>
#include<cmath>
#define maxn 200007
using namespace std;
struct node {
    double x, y;
    bool operator<(const node& A) {
        if (x != A.x)return x < A.x;
        return y < A.y;
    }
}point[maxn];
int temp[maxn << 1], n;
double dis(node a, node b)
{
    double x = (a.x - b.x) * (a.x - b.x);
    double y = (a.y - b.y) * (a.y - b.y);
    return sqrt(x + y);
}
double daq(int l, int r)
{
    if (l == r)
        return 1e9;
    //由于是计算点对距离,需要如下的特判来提供距离
    if (l + 1 == r)
        return dis(point[l], point[r]);
    int m = l + r >> 1, k = 0;
    //先找出左右区间点对最优解
    double d = min(daq(l, m), daq(m + 1, r));
    //第一次剪枝
    for (int i = l; i <= r; i++)
        if (fabs(point[i].x - point[m].x) < d)
            temp[++k] = i;
    //计算点对距离时,再次剪枝优化复杂度
    for (int i = 1; i < k; i++)
        for (int j = i + 1; j <= k && fabs(point[temp[i]].x - point[temp[j]].x) < d; j++)
            d = min(d, dis(point[temp[i]], point[temp[j]]));
    return d;
}
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> point[i].x >> point[i].y;
    sort(point + 1, point + n + 1);
    printf("%.4lf", daq(1, n));
    return 0;
}

 

标签:跨界点,point,距离,最近,平面,区间,P1429,最优,include
来源: https://www.cnblogs.com/xqk0225/p/16147282.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有