C++ 两点之间最短距离

两点之间最短距离

这是我的一个测试,也是我学习html的/起点,他们说一个合格的程序员必须学会html,我比他们起步晚了一些,可是我认为还来的及,以后我就用html来记录我的学习记录了。

问题的提出:
在二维平面的n个点上,找出其中的一对点,使得在n个点组成的所有的点中,该点对的距离最小。


一维:最接近点对问题

方法一:(暴力法)
  直接使用双层遍历来计算每一对点的距离,另外新建一个变量记录两点之间距离最小的值,但是如此一来时间复杂度就变为O(n2),

方法二:(分治法)
分治法的思路:

  1. 划分成子规模点集S1和S2;
  2. 找到S1和S2的最小距离d;
  3. 合并S1和S2:利用d在S1的(m-d,m]和S2(m,m+d]中找到最大点和最小点,即p3和q3.选出最小距离,完成合并。

![示意图](https://img-blog.csdnimg.cn/20201004201704741.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNTExOTY0,size_16,color_FFFFFF,t_70#pic_center)

m如何选择
m=(max(s)+min(s))/2;


代码:
talking is cheap,show me the code;
/*根据算法随便写的,返回的是两个点之间最小的距离,不是两个点的坐标,如果有问题,欢迎指正*/
/*这里的坐标默认为正序的*/
#include<iostream>
#include<vector>
using namespace std;
int search(vector<int> target)
{   
int n=target.size();   
if(n<2)   //如果分到一个元素就返回最大数值
return INT_MAX;   
int mid=n/2;   //中线
vector<int> temp_left;  
 vector<int> temp_right;   temp_left.insert(temp_left.begin(),target.begin(),target.begin()+mid); //中线分割  temp_right.insert(temp_right.begin(),target.begin()+mid,target.end());  
 int p=search(temp_left);  
 int q=search(temp_right);  
 int d=temp_right.front()-temp_left.back();  
 cout<<temp_right.front()<<" "<<temp_left.back()<<endl;  
return d>min(p,q)?min(p,q):d;}//返回两边和贯穿中间的最小的两点距离
 int main(){    
 int a[6]={-9,-6,0,4,7,9};    
 vector<int> target(a,a+6);    
cout<<search(target);    
return 0;
}
二维最接近点的问题:

思路与一维的最接近点对相似。

  1. 选取中垂线l:x=m来作为分割直线。
  2. 递归的在S1和S2找出其最小距离d1和d2,并设d=min{d1,d2},S中最接近点对或是d,或者是某个{p,q}
  3. 合并起来

// 随便写思路的如果有误,请指正(注意返回的是两点之间的距离,不是坐标)
#include <iostream>
#include <math.h>
#include<algorithm>
using namespace std;
struct point
{
	int x, y;
};
double distance(struct point p1, struct point p2)
{
	return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y,2));
}
double search(struct point p[],int pl,int pr)
{
	if (pl == pr)
		return INT_MAX;
	int mid = (pl + pr) / 2;
	double d_left = search(p, pl, mid);
	double d_right = search(p, mid + 1, pr);
	double temp_d = min(d_left, d_right);
	while (abs(p[pl].y - p[mid].y) > temp_d&&pl < pr)//如果仅仅是单边距离就已经大于上一次比较返回的d就没必要在接下来的敌方继续比较了。
		pl++;
	while (abs(p[pr].y - p[mid].y) > temp_d&&pl < pr)
		pr--;
	for (int i = pl; i < pr; i++)
	{
		for (int j = i + 1; j < pr; j++)
		{
			if (temp_d < abs(p[i].x - p[j].x))//同理与上面的注释
				break;
			else
				temp_d = min(temp_d, distance(p[i], p[j]));//找到最小的距离
		}
	}
	return temp_d;
}
int main()
{
	struct point p[100];
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> p[i].x;
		cin >> p[i].y;
	}
	cout<<search(p, 0, n - 1);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值