Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >最近点对问题

最近点对问题

作者头像
AI那点小事
发布于 2020-04-20 04:34:53
发布于 2020-04-20 04:34:53
58100
代码可运行
举报
文章被收录于专栏:AI那点小事AI那点小事
运行总次数:0
代码可运行

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <ctime> 
#define MAX_DISTANCE 999999
using namespace std;

typedef struct point{
	double x;	//横坐标
	double y;	//纵坐标 
}Point;

Point *PointsX;
Point *PointsY;
Point minPoint1, minPoint2;			//二维点最优数组 
int n;								//二维点个数 

//按横坐标升序排序规则函数 
bool cmpX(Point point1,Point point2)
{
	return point1.x < point2.x;
}

//按纵坐标升序排序规则函数
bool cmpY(Point point1,Point point2)
{
	return point1.y < point2.y;
}

//计算两点间的距离 
double Distance(Point point1,Point point2)
{
	double distx = pow(point1.x-point2.x,2);
	double disty = pow(point1.y-point2.y,2);
	return sqrt(distx+disty);
}

//归并排序的合并整理操作
void Merge(int left, int right)
{
 
	int mid = (left + right) / 2;
	int i = left, j = mid + 1;
	int idx = left;
 
	while(i <= mid && j <= right) {
		if (PointsX[i].y < PointsX[j].y){
			PointsY[idx++] = PointsX[i++];	
		}else{
			PointsY[idx++] = PointsX[j++];	
		} 
	}
 
	while(i <= mid){
		PointsY[idx++] = PointsX[i++];	
	} 
	while(j <= right){
		PointsY[idx++] = PointsX[j++];	
	}
	for(i = left; i <= right; i++){
		PointsX[i] = PointsY[i];
	}
}

double MergeMethod(Point *px, int l, int r, Point &p1, Point &p2)
{
	if(r - l <= 0){//点数为1时输出无穷大
		return MAX_DISTANCE;
	}else if(r - l == 1){		//点数为2直接输出点距同时记录点对
		Merge(l,r);
		p1 = px[l];
		p2 = px[r];
		return Distance(p1,p2);
	}else{
		Point c, d, e, f;
		double mindis;
		int i, j;
		int mid = (r + l) / 2;		//前面已排好序,直接平均分
		double middlex = PointsX[mid].x;	//记录中线的x值,用于后面判断和存储中间区域的点
		double mindis1 = MergeMethod(px, l, mid, c, d);		//求左边部分的最短点距
		double mindis2 = MergeMethod(px, mid+1, r, e, f);	//求右边部分的最短点距
		if(mindis1 < mindis2){		//两边比较取最小值,并记录点对
			mindis = mindis1;
			p1 = c;
			p2 = d;
		}else{
			mindis = mindis2;
			p1 = e;
			p2 = f;
		}
		Point *temp = new Point[r - l + 1];		//将所有与中间点的横坐标距离小于mindis的点纳入数组
		int number = 0;
		Merge(l, r);			//对点进行合并操作,之后的数组已是按y值排好的数组
		for(i = l; i <= r; i++){
			if(fabs(px[i].x - middlex ) <= mindis){	//数组内的数据相当于在横坐标范围[middlex-mindis,middlex+mindis]之间
				temp[number++] = px[i];
			}
		}
		double tempdis;		//遍历中间数组,每个点最多遍历其他点6次,记录最短距离和点对
		for(i = 0; i < number; i++){
			for(j = i + 1; j < i+1+6 && j < number; j++){
				tempdis = Distance(temp[i],temp[j]);
				if(tempdis < mindis){
					mindis = tempdis;
					p1 = temp[i];
					p2 = temp[j];
				}
			}
		}
		delete[]temp;
		return mindis;
	}
}

//随机生成点
void CreatePoints(Point* Points, int pointNumber)
{
	srand(time(NULL));		//随机化随机数种子
	for(int i = 0; i<pointNumber; i++){
		Points[i].x = rand() / (double)RAND_MAX;
		Points[i].y = rand() / (double)RAND_MAX;
		//每1000个数据乘以一个特定的数,将数据尽量分散,减少重复
		Points[i].x *= ((i / 1000) + 1);
		Points[i].y *= ((i / 1000) + 1);
		//遍历已经生成的所有点,一旦发现重合则重新生成该点
		for (int j = 0; j < i; j++){
			if (Points[j].x == Points[i].x && Points[j].y == Points[i].y) {
				i--;
				break;
			}
		}
	}
}

int main()
{
	cout<<"请输入二维点个数:"<<endl;
	cin>>n; 
	PointsX = new Point[n];
	CreatePoints(PointsX, n);			//创建散点	
	cout<<"随机生成的二维点坐标为:"<<endl;
	for(int i = 0 ; i < n ; i++){
		cout<<"("<<PointsX[i].x<<","<<PointsX[i].y<<")"<<endl; 
	} 
	sort(PointsX, PointsX + n, cmpX);		//对点以X坐标进行排序
	PointsY = new Point[n];		//创建新数组在Merge合并操作时用
	double dis = MergeMethod(PointsX, 0, n - 1, minPoint1, minPoint2);	//调用分治法
	if(dis == MAX_DISTANCE){
		cout<<"不存在最近点对"<<endl; 
	}else{
		cout<<"最近点对为:"<<endl;
		cout<<"("<<minPoint1.x<<","<<minPoint1.y<<")"<<endl; 
		cout<<"("<<minPoint2.x<<","<<minPoint2.y<<")"<<endl; 
		cout<<"最近距离为:"<<dis<<endl;	
	}
	
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
2020安徽程序设计省赛 I美丽几何
在平面上有n 个点,初始每个点的美丽值都为0,任意选择两个点组成一条直线,对于每一条直线,如果存在一个点,这个点到这条直线的距离小于其他n-3 个点到这条直线的距离,那么我们把这个点的美丽值加1。为了简化输出,我们只需要输出所有点的美丽值的异或值,保证三点不共线。
程序员小涛
2021/12/06
5450
POJ2253 && ZOJ1942
两种写法 用floyd算法,求所有点之间的最大跳的最小值,最后输出a[0][1],即起始与终止位置的最小值,采用传递闭包的思路,时间复杂度较高,但代码简单。 或者Dijkstru的变形,两点间的最短距离,只是最短距离的求法有变,当前加入一个点时,松弛方法不同,时间复杂度降低了。 在数据结构编程实验一书上,看到二分的写法,感觉很巧妙。也是把三种写法都看一下,前两种为找到的代码,最后一种是自己写的。 floyd #include<stdio.h> #include<math.h>
triplebee
2018/01/12
5230
FZU Moon Game(几何)
Accept: 710    Submit: 2038 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description Fat brother and Maze are playing a kind of special (hentai) game in the clearly blue sky which we can just consider as a kind of two-dimensional plane. Then
ShenduCC
2018/04/26
6380
令人闻风丧胆的NEERC——被称为ICPC题目质量之最的比赛,究竟是怎样的难度
NEERC,ACM-ICPC Northeastern European Regional Contest,是欧洲地区的异常区域赛,因其题目质量高而闻名于ICPC。
ACM算法日常
2021/09/28
1.8K0
原 初学算法-分治法求平面上最近点对(Cl
    本来这个算法在笔者电脑里无人问津过一段时间了,但今天正好做HDU 1007见到了这个问题,今天就来把代码分享出来吧!     我们首先将所有点按照坐标x排序一下,再做一条直线l当作“分割线”,方便我们递归。     然后,我们就可以把这些点按照x轴的坐标分为左半部分和右半部分。那么最短距离一定在左半部分、右半部分、跨越左右的点对中的一个。      那么你可能会有疑问了:本来最近点对也一定在这三个区域内,这不还是相当于什么都没干吗?     还真不是。我们可以假设通过递归得到了左边最小距离为d
不高不富不帅的陈政_
2018/05/18
1.5K0
杭电 1007(最近点对问题,最详细的思路解析过程)
思路:我一开始没怎么想,就暴力着把所有的点都遍历一遍,然后每次两个坐标得到一个距离,然后每次min得到最小的距离,所有的点遍历后就能得到最小距离。(超时!!!) 下面是错误代码,只考虑了相邻的两个点间的距离,我们必须要用两个for循环把所有的两两点遍历得到最小距离
杨鹏伟
2020/09/11
5500
gis如何无缝拼接两张图_arcgis多幅影像图拼接
#include “opencv2/features2d/features2d.hpp” #include “opencv2/highgui/highgui.hpp” #include “opencv2/opencv_modules.hpp” #include “opencv2/calib3d/calib3d.hpp”
全栈程序员站长
2022/11/09
6790
AcWing 528. 奶酪(每日一题)
现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。
摆烂小白敲代码
2024/09/23
1120
AcWing 528. 奶酪(每日一题)
knn之构造kd树和最近邻求取c++实现
这样,通过中位数来选取根节点(这样的方法其实在一定程度上是有很大问题的,因为根节点的选取方法不同,会导致整棵树的结构不同,这里由于数据的关系,不能构成完全二叉树,所以在对于特殊的样例来说是会出错的,比如说(10,10)这个测试样例,根本无法找到包含他的子节点(区域),所以会导致出错))。
用户7886150
2021/02/12
5850
ACM计算几何篇_acm数学
https://linxi99.gitee.io/20190211/ACM计算几何篇/
全栈程序员站长
2022/11/19
1.4K0
ACM计算几何篇_acm数学
BZOJ 3053: The Closest M Points(K-D Tree)
Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1235  Solved: 418 [Submit][Status][Discuss] Description The course of Software Design and Development Practice is objectionable. ZLC is facing a serious problem .There are many points in K-dimensional space
attack
2018/05/30
3480
OpenCV 直线拟合及应用
该文介绍了使用OpenCV库进行直线拟合的方法,包括各种距离度量方法,以及使用线性回归进行直线拟合,并给出了具体的示例代码和注释。
chaibubble
2018/01/02
2.4K0
OpenCV 直线拟合及应用
Codeforces Round #725 (Div. 3)
n个石子排成一排,每个石子有一个能力值,且每个石子的能力值各不相同,每次可以销毁最左边的石子或者最右边的石子,问最少几次消除能力值最大和最小的石子。
Here_SDUT
2022/08/08
2750
Codeforces Round #725 (Div. 3)
分治应用--最近点对问题 & POJ 3714
假如在这个范围内的有1,2,3,4,5,6六个点(按 y 坐标排序),寻找距离小于 d 的点对,如果暴力查找,复杂度还是 n2,我们可以看出点4只有可能在其上下y坐标 ± d 的范围内找到满足距离小于 d 的点匹配,点1和点4不可能距离小于 d,左边的点最多可以有4个右边的点使得其距离小于 d
Michael阿明
2021/02/20
9030
分治应用--最近点对问题 & POJ 3714
使用Hashtable来检验随机数的随机性
1.首先是创建Hashtable,使用for循环和定义一个产生随机数的r,key值对应随机数的value值。
Java进阶者
2021/12/31
2380
使用Hashtable来检验随机数的随机性
高翔Slambook第七讲代码解读(3d-3d位姿估计)
上回咱们读完了pose_estimation_3d2d.cpp这个程序,也找到了3d-2d位姿估计与2d-2d位姿估计之间的联系与差别:
小白学视觉
2019/10/24
2.3K1
高翔Slambook第七讲代码解读(3d-3d位姿估计)
hdu1007平面最近点对分治
分治即可,对N对点对,求中间值,mid。按照横坐标升序排列,递归求出0到mid以及mid+1到N-1对点的最小距离。
用户2965768
2018/08/30
6440
《算法竞赛进阶指南》0x08 总结与练习
任何问题都有其涉及的范围,称之为问题的“状态空间”,求解一个问题,就是在这个状态空间里的遍历与映射
一只野生彩色铅笔
2022/10/31
7980
《算法竞赛进阶指南》0x08 总结与练习
【C++】考研408代码题【必会】【收藏】
浮点有精度限制 一旦涉及计算 就会导致舍入,所以 要用数学表达 非常接近 就是||<epsilon
20岁爱吃必胜客
2022/11/13
4150
【C++】考研408代码题【必会】【收藏】
Python使用系统聚类算法对随机元素进行分类
系统聚类算法又称层次聚类或系谱聚类,首先把样本看作各自一类,定义类间距离,选择距离最小的一对元素合并成一个新的类,重复计算各类之间的距离并重复上面的步骤,直到将所有原始元素分成指定数量的类。该算法的计算复杂度比较高,不适合大数据聚类问题。 from random import randrange def generate(s, m1, m2): '''生成形式如[('a', (1,5)), ('b', (3,6))]的随机坐标''' x = [(ch, (randrange(m1), randra
Python小屋屋主
2018/04/16
1.5K0
Python使用系统聚类算法对随机元素进行分类
相关推荐
2020安徽程序设计省赛 I美丽几何
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文