洛谷Oj-平面上的最接近点对-分治

来源:互联网 发布:python 量化 书籍 编辑:程序博客网 时间:2024/06/05 10:20

学习资料

yi5http://blog.csdn.net/jpwang8/article/details/55056957
http://blog.csdn.net/C20190102/article/details/75174797?locationNum=2&fps=1

问题描述

给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的。

代码

struct point//点{    double x;    double y;};point p[10010];//最多10000个点double dis(point a,point b)//计算两点间的欧几里得距离{    //if(a.x == b.x && a.y == b.y)//想到有可能会计算自己到自己的距离,但这样写是错误的,正确的方法应该是在算法中避免        //return inf;    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}bool cmp1(point a,point b){    return a.x < b.x || a.x == b.x && a.y < b.y;//①a.x < b.x返回真②a.x > b.x返回假③a.x == b.x并根据a.y < b.y返回真假,写得很巧妙,但是容易出错}bool cmp2(point a,point b){    return a.y < b.y;}double fun(int l,int r)//对已经排好序的数组进行分析!{    if(l == r)//边界,只有一个点        return inf;//返回一个不影响结果的值,所以返回无穷大    if(l + 1 == r)//边界,只有两个点        return dis(p[l],p[r]);//返回两点间的距离    int mid = (l + r) / 2;//二分    double d1 = fun(l,mid);//计算左半平面中点对的最小距离    double d2 = fun(mid + 1,r);//计算右半平面中点对的最小距离    double d = min(d1,d2);//取较小值    vector<point> v;//储存[mid - d,mid + d]内的点    for(int i = l; i <= r; ++i)        if(p[i].x >= p[mid].x - d && p[i].x <= p[mid].x + d)//用fabs(p[i].x - p[mid].x) <= d更好            v.push_back(p[i]);//加入    sort(v.begin(),v.end(),cmp2);//按y坐标由小到大排序    int siz = v.size();//防止重复计算,减少时间开销    for(int i = 0; i <= siz - 1; ++i)//固定一个点,与它后面的点比较,选择排序的思想,保证了每两个点都比较过了。比较暴力        for(int j = i + 1; j <= siz - 1; ++j)//i + 1便保证了不会求自身到自身的距离            if(v[j].y - v[i].y < d)//如果比d小                d = min(d,dis(v[i],v[j]));//更新答案    return d;//返回}int main(){    int n;    //输入    cin >> n;    for(int i = 1; i <= n; ++i)        scanf("%lf%lf",&p[i].x,&p[i].y);    sort(p + 1,p + n + 1,cmp1);//按x坐标由小到大排列,若x坐标相同,就按y坐标由小到大排列    double ans = fun(1,n);//调用    printf("%.4lf\n",ans);//打印    return 0;}

解决方法:
生动形象的说明请看学习资料中推荐的网站。题目扩展:求曼哈顿距离