平面最接近点对问题(分治法)

Posted outthinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平面最接近点对问题(分治法)相关的知识,希望对你有一定的参考价值。

问题描述参见:https://www.cnblogs.com/zyxStar/p/4591897.html

代码参考:http://blog.csdn.net/qq_28666193/article/details/53351482(原代码中有几处错误,我作了修改)

头文件部分

(1)数据结构部分:

//涉及的数据结构
#ifndef DATASET_H
#define DATASET_H

struct point{  //点结构
    double x, y;
};

#endif

(2)函数声明部分:

//函数头文件
//=======================================
#ifndef FUNC_H
#define FUNC_H

#include "dataset.h"

double closest_distance(point s[], int low, int high, point rec[]);
double Distance(point a, point b);
bool comp_x(point a, point b);
bool comp_y(point a, point b);

#endif

 

源文件部分

(1)函数实现部分:

//求解最近距离的函数实现
#include "dataset.h"
#include <math.h>
#include <algorithm>

using namespace std;

double Distance(point a, point b)  //计算两点距离
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) - (a.y - b.y));
}

bool comp_x(point a, point b)  //按x升序判别函数
{
    return a.x < b.x;
}

bool comp_y(point a, point b)  //按y升序判别函数
{
    return a.y < b.y;
}
//函数实现:rec[]存储最接近点对;
double closest_distance(point s[], int low, int high, point rec[])
{
    double d1, d2, d3, d;
    int mid, i, j, index;
    double x1, y1, x2, y2; //记录最近的点对
    point *P = new point[high - low + 1];
    point temp_1[2], temp_2[2], temp_3[2];

    if (high - low == 1)  //两个点时的情况
    {
        rec[0].x = s[low].x; rec[0].y = s[low].y;
        rec[1].x = s[high].x; rec[1].y = s[high].y;
        return Distance(s[low], s[high]);
    }

    if (high - low == 2)  //三个点时的情况
    {
        d1 = Distance(s[low], s[low + 1]);
        d2 = Distance(s[low + 1], s[high]);
        d3 = Distance(s[low], s[high]);
        if ((d1 <= d2) && (d1 <= d3))  //这里在判断三种情况时,第二种情况没必要使用(d2<d3)&&(d2<d1),相较更繁琐了;
        {
            rec[0].x = s[low].x; rec[0].y = s[low].y;
            rec[1].x = s[low + 1].x; rec[1].y = s[low + 1].y;
            return d1;
        }
        else if (d2 < d3)
        {
            rec[0].x = s[low + 1].x; rec[0].y = s[low + 1].y;
            rec[1].x = s[high].x; rec[1].y = s[high].y;
            return d2;
        }
        else
        {
            rec[0].x = s[low].x; rec[0].y = s[low].y;
            rec[1].x = s[high].x; rec[1].y = s[high].y;
            return d3;
        }
    }

    mid = (low + high) / 2;
    d1 = closest_distance(s, low, mid, rec);
    temp_1[0] = rec[0];
    temp_1[1] = rec[1];
    d2 = closest_distance(s, mid + 1 ,high, rec);
    temp_2[0] = rec[0];
    temp_2[1] = rec[1];
    if (d1 <= d2)
    {
        d = d1;
        rec[0] = temp_1[0];
        rec[1] = temp_1[1];
    }
    else
    {
        d = d2;
        rec[0] = temp_2[0];
        rec[1] = temp_2[1];
    }
    index = 0;
    for (i = mid; (i >= low) && ((s[mid].x - s[i].x) < d); i--)
    {
        P[index++] = s[i];  //点集合P1
    }
    for (i = mid + 1; (i <= high) && ((s[i].x - s[mid].x) < d); i++)
    {
        P[index++] = s[i];  //点集合P2
    }
    sort(P, P + index, comp_y);  //升序排列
    for (i = 0; i < index; i++)
    {
        for (j = i + 1; j < index; j++)
        {
            if ((P[j].y - P[i].y) >= d)
                break;
            else
            {
                d3 = Distance(P[i], P[j]);
                if (d3 < d)
                {
                    rec[0].x = P[i].x; rec[0].y = P[i].y;
                    rec[1].x = P[j].x; rec[1].y = P[j].y;
                    d = d3;
                }
            }
        }
    }
    delete []P;  //注意动态内存的删除方式,防止内存泄漏
    return d;
}

 

(2)主函数部分:

//2018_02_24
//使用分治法求解二维平面最接近点问题
//=============================================================
#include <iostream>
#include <math.h>
#include <algorithm>
#include "dataset.h"  //数据结构实现放在这个头文件中
#include "func.h"  //函数声明的头文件

using namespace std;

int main(void)
{
    point p[10];  //设定点的集合
    int n;
    double minDist;
    cout << "输入点的个数:\\n";
    cin >> n;
    cout << "输入点集:(x , y) \\n";
    for (int i = 0; i < n; i++)
        cin >> p[i].x >> p[i].y;
    sort(p, p + n, comp_x);  //对输入的点先进行排序
    point index[2];
    minDist = closest_distance(p, 0, n - 1, index);
    cout << "最小距离点对为:(" << index[0].x << "," << index[0].y << "),(" << index[1].x << "," << index[1].y << ")";
    cout << "最小距离为:\\n" << minDist;
    system("pause");
    return 0;
}

 

最后,结果如下:

 

以上是关于平面最接近点对问题(分治法)的主要内容,如果未能解决你的问题,请参考以下文章

平面最接近点对

洛谷P1257 平面上的最接近点对 数学 分治 排序

分治法二(平面最近点对)

平面点集最接近点对问题怎么做

POJ 3714 分治/求平面最近点对

最小点对分治法(洛谷1257)