分治法求解最近点距

2023-10-24 19:20
文章标签 分治 最近 求解 点距

本文主要是介绍分治法求解最近点距,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.问题描述:

最近点对问题很简单,就是给定一堆点(这里是二位坐标下),求解最近的点的距离,该问题可以用穷举法求解,双重循环就够了,就不说了,主要看一下分治法的代码,代码也很简单,有注释。

2.分治法求解:

1

代码如下:

采用C++类模板编写
编译环境VS2015

#include <stdio.h>
#include <tchar.h>
#include"math.h"
#include<iostream>
using namespace std;//定义PointX以及PointY类,设定其编号,x,y坐标以及<=运算符,主要是因为
//按X坐标排序和按Y坐标排序时所比较的坐标不相同,因此不能采用同一个类。
//采用两个类可简化算法的复杂度。
class PointX {
public:int operator<= (PointX a)const{return (x <= a.x);}
public:int ID;float x, y;
};class PointY {
public:int operator<= (PointY a)const{return (y <= a.y);}
public:int p;float x, y;
};//通过模板可使函数的通用性更强
template <class T>
inline float Distance(const T &u, const T &v);
bool CPair2(PointX X[], int n, PointX &a, PointX &b, float &d);
template <class T>
void MergeSort(T a[], int n);
template <class T>
void MergePass(T x[], T y[], int s, int n);
template <class T>
void Merge(T c[], T d[], int l, int m, int r);
void closest(PointX X[], PointY Y[], PointY Z[], int l, int r, PointX &a, PointX &b, float &d);int main()
{int n;PointX *X, a, b;float d;cout << "Please input the number of points:" << endl;cin >> n;X = new PointX[n];cout << "Please input the coordinate of the points:" << endl;for (int i = 0; i<n; i++) {cout << "X Y:";cin >> X[i].x >> X[i].y;X[i].ID = i;}CPair2(X, n, a, b, d);cout << "min distance: " << d <<endl;delete[] X;return 0;
}//求任意两点之间的距离
template <class T>
inline float Distance(const T &u, const T &v)
{float dx = u.x - v.x;float dy = u.y - v.y;return sqrt(dx*dx + dy*dy);
}//按x坐标和y坐标排序,并求点对。按y坐标排序的点记录了其原来在排好序之后的X数组中的位置。
//Y数组主要用于存储某分界线两端的点,并使其按Y坐标的大小进行排列,以便于计算。
bool CPair2(PointX X[], int n, PointX &a, PointX &b, float &d)
{if (n<2)return false;MergeSort(X, n);PointY *Y = new PointY[n];for (int i = 0; i<n; i++) {Y[i].p = i;Y[i].x = X[i].x;Y[i].y = X[i].y;}MergeSort(Y, n);PointY *Z = new PointY[n];closest(X, Y, Z, 0, n - 1, a, b, d);delete[] Y;delete[] Z;return true;
}
//用分治法实现的归并排序算法,该函数实现将长度为s的两段序列合并成一段。
template <class T>
void MergeSort(T a[], int n)
{T *b = new T[n];int s = 1;while (s<n) {//将a中的数合并到b中MergePass(a, b, s, n);//s增加一倍,使得合并步长增加一倍。s += s;//将b中的数合并到a中MergePass(b, a, s, n);s += s;}
}//将相邻两段排好序的数组合并成有序序列。
template <class T>
void MergePass(T x[], T y[], int s, int n)
{int i = 0;while (i <= n - 2 * s) {//将x中相邻两段长度为s的有序序列合并成一个,并放在y中。Merge(x, y, i, i + s - 1, i + 2 * s - 1);i = i + 2 * s;}//若x中还有剩余,则将剩余的元素少于2s合并到y中if (i + s<n)Merge(x, y, i, i + s - 1, n - 1);elsefor (int j = i; j <= n - 1; j++)y[j] = x[j];
}//将c[l...m]中的元素和c[m+1...r]中的元素合并在d中。
template <class T>
void Merge(T c[], T d[], int l, int m, int r)
{int i = l, j = m + 1, k = l;while ((i <= m) && (j <= r))//谁小谁先放if (c[i] <= c[j])d[k++] = c[i++];elsed[k++] = c[j++];if (i>m)for (int q = j; q <= r; q++)d[k++] = c[q];elsefor (int q = i; q <= m; q++)d[k++] = c[q];}
//求最小点对及距离
void closest(PointX X[], PointY Y[], PointY Z[], int l, int r, PointX &a, PointX &b, float &d)
{//如果2个点,直接求距离if (r - l == 1) {a = X[l];b = X[r];d = Distance(X[l], X[r]);return;}//如果3个点,则两两计算求最小距离及点对。if (r - l == 2) {float d1 = Distance(X[l], X[l + 1]);float d2 = Distance(X[l + 1], X[r]);float d3 = Distance(X[l], X[r]);if (d1 <= d2 && d1 <= d3) {a = X[l];b = X[l + 1];d = d1;return;}if (d2 <= d3) {a = X[l + 1];b = X[r];d = d2;}else {a = X[l];b = X[r];d = d3;}return;}//其他情况采用二分法分割成几段来求int m = (l + r) / 2;int f = l, g = m + 1;//m将l,r分割成两段,分别求m两边的点,并按照y坐标的大小排列,放在Z数组中for (int i = l; i <= r; i++)if (Y[i].p>m)Z[g++] = Y[i];elseZ[f++] = Y[i];//求l...m间所有点最小点对及距离closest(X, Z, Y, l, m, a, b, d);float dr;PointX ar, br;//求m+1...r间所有点的最小点对及距离closest(X, Z, Y, m + 1, r, ar, br, dr);//求两边点中最小点对及距离。if (dr<d) {a = ar;b = br;d = dr;}//将m两边的点合并到Y数组中,并按Y坐标大小排列Merge(Z, Y, l, m, r);//取矩形条内的点int k = l;for (int i = l; i <= r; i++)if (fabs(Y[m].x - Y[i].x)<d)Z[k++] = Y[i];//求矩形条内的点的最小距离及点对,并与前面求得的点距比较,取最小。for (int i = l; i<k; i++) {for (int j = i + 1; j<k && Z[j].y - Z[i].y<d; j++) {float dp = Distance(Z[i], Z[j]);if (dp<d) {d = dp;a = X[Z[i].p];b = X[Z[j].p];}}}
}

这篇关于分治法求解最近点距的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/277245

相关文章

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

最近心情有点复杂:论心态

一月一次的彷徨又占据了整个身心;彷徨源至不自信;而不自信则是感觉自己的价值没有很好的实现亦或者说是自己不认可自己的目前的生活和状态吧。 我始终相信一句话:任何人的生活形态完全是由自己决定的;外在的总归不能直达一个人的内心深处。所以少年 为了自己想要的生活 多坚持努力吧、不为别人只为自己心中的那一丝执着。 由此我看到了一个故事: 一个心情烦躁的人去拜访禅师。他问禅师:我这辈子就这么注定了吗?您

2024 年高教社杯全国大学生数学建模竞赛题目——2024 年高教社杯全国大学生数学建模竞赛题目的求解

2024 年高教社杯全国大学生数学建模竞赛题目 (请先阅读“ 全国大学生数学建模竞赛论文格式规范 ”) 2024 年高教社杯全国大学生数学建模竞赛题目 随着城市化进程的加快、机动车的快速普及, 以及人们活动范围的不断扩大,城市道 路交通拥堵问题日渐严重,即使在一些非中心城市,道路交通拥堵问题也成为影响地方经 济发展和百姓幸福感的一个“痛点”,是相关部门的棘手难题之一。 考虑一个拥有知名景区

在二叉树中找到两个节点的最近公共祖先(基于Java)

如题  题解 public int lowestCommonAncestor(TreeNode root, int o1, int o2) {//记录遍历到的每个节点的父节点。Map<Integer, Integer> parent = new HashMap<>();Queue<TreeNode> queue = new LinkedList<>();parent.put(roo

基于SA模拟退火算法的多车辆TSP问题求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述        基于SA模拟退火算法的多车辆TSP问题求解matlab仿真,三个车辆分别搜索其对应的最短路径,仿真后得到路线规划图和SA收敛曲线。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 (完整程序运行后无水印)

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

算法图解(8~10贪心,动态规划,K最近邻算法)

贪心算法 在每一步都选择局部最优解,从而期望最终得到全局最优解。 贪心算法并不总能保证全局最优解,因此需要满足以下两个条件: 贪心选择性质:可以通过局部最优选择构造出全局最优解。最优子结构:问题的最优解包含其子问题的最优解。 实例:给定面额的硬币,用最少硬币凑出指定金额 int minCoins(vector<int>& coins, int amount) {int count = 0

JD 1147:Jugs(一种用最少步骤求解的方法)

OJ题目:click here~~ 题目分析:九度上这道没有要求最少步数,只要得到最后结果即可AC , bfs , dfs都行。最少步骤的方法肯定也能AC啦,分析如下。 输入的三个数:a,b,n;> 由题不定方程ax+by=n必定有解> 如果b=n,则fill B即可,否则用试探法求出这样的两组解(a1,b1)及(a2,b2),其中a1 >0,b1<0;a1是满足方程的最小正整数;a2