平面最近点对(加强版)

本文介绍了一种算法,用于在给定的二维平面上n个点中找到任意两点之间的最短距离。通过C++实现,利用排序和合并区间的方法来优化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

输入

第一行:n ,保证 2≤n≤200000 。

接下来 n 行:每行两个实数:x ,y 表示一个点的行坐标和列坐标,中间用一个空格隔开

输出

仅一行,一个实数,表示最短距离,精确到小数点后面 4 位。

AC代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e4+10;
typedef long long LL;
struct node
{
	double x,y;
}p[N];
int temp[N];
bool cmp(const node &a,const node &b)
{
	if(a.x==b.x)
	return a.y<b.y;
	else
	return a.x<b.x;
}
bool cmp2(const int &a,const int &b)
{
	return p[a].y<p[b].y;
}
double dis(int i,int j)
{
	return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
double merge(int l,int r)
{
	double res=0x3f3f3f3f; 
	if(l>=r)
	return res;
	int mid=l+r>>1;
	res=min(merge(l,mid),merge(mid+1,r));
	int k=0;
	for(int i=l;i<=r;i++)
	{
		if(fabs(p[mid].x-p[i].x)<res)
		{
			temp[k++]=i; 
		}
		sort(temp,temp+k,cmp2);
		for(int i=0;i<k;i++)
		{
			for(int j=i+1;j<k;j++)
			{
				if(fabs(p[temp[j]].y-p[temp[i]].y)<res) 
				res=min(res,dis(temp[j],temp[i])); 
			}
		}

	}
	return res;
}

int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		double x,y;
		cin>>x>>y;
		p[i].x=x;
		p[i].y=y;
	}
	sort(p,p+n,cmp);
	printf("%.4lf\n",merge(0,n-1));
}

运行结果 

(电脑截图坏了,请谅解)

宋江,卢俊义,吴用,公孙胜,关胜,林冲,秦明,呼延灼,花荣,柴进,李应,朱仝,鲁智深,武松,董平,张清,杨志,徐宁,索超,戴宗,刘唐,李逵,史进,穆弘,雷横,李俊,阮小二,张横,阮小五,张顺,阮小七,杨雄,石秀,解珍,解宝,燕青,朱武,黄信,孙立,宣赞,等108人觉得很赞您确定不来一个吗?

### Python 实现平面最近点对问题(加强版) #### 分治法解决平面最近点对 分治法是一种经典的算法设计策略,用于高效求解复杂问题。对于平面最近点对问题,其核心思想是将平面上的点集划分为两个子集,分别计算每个子集中最短距离,并通过合并阶段找到跨越两部分的可能更近的距离。 以下是基于分治法的 Python 实现: ```python import math from typing import List, Tuple def distance(p1: Tuple[float, float], p2: Tuple[float, float]) -> float: """ 计算两点之间的欧几里得距离 """ return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2) def brute_force(points: List[Tuple[float, float]]) -> float: """ 使用暴力方法计算最小距离 """ min_dist = float(&#39;inf&#39;) n = len(points) for i in range(n): for j in range(i + 1, n): dist = distance(points[i], points[j]) if dist < min_dist: min_dist = dist return min_dist def strip_closest(strip: List[Tuple[float, float]], d: float) -> float: """ 处理跨区域的情况,在带状区域内查找更小的距离 """ min_dist = d size = len(strip) strip.sort(key=lambda point: point[1]) # 按 y 坐标排序 for i in range(size): for j in range(i + 1, size): if (strip[j][1] - strip[i][1]) >= min_dist: # 提前剪枝 break dist = distance(strip[i], strip[j]) if dist < min_dist: min_dist = dist return min_dist def closest_pair_recursive(px: List[Tuple[float, float]], py: List[Tuple[float, float]]) -> float: """ 主递归函数,px 是按 x 排序的点列表,py 是按 y 排序的点列表 """ n = len(px) if n <= 3: # 当点数较少时采用暴力法 return brute_force(px) mid = n // 2 midpoint = px[mid] # 将 py 划分成左右两半 pyl = [] pyr = [] for point in py: if point[0] <= midpoint[0]: pyl.append(point) else: pyr.append(point) dl = closest_pair_recursive(px[:mid], pyl) # 左侧递归调用 dr = closest_pair_recursive(px[mid:], pyr) # 右侧递归调用 d = min(dl, dr) # 构造中间条带内的点集合 strip = [] for point in py: if abs(point[0] - midpoint[0]) < d: strip.append(point) return min(d, strip_closest(strip, d)) def closest_pair(points: List[Tuple[float, float]]) -> float: """ 调度函数,负责初始化输入数据并启动递归过程 """ px = sorted(points, key=lambda point: point[0]) # 按 x 坐标排序 py = sorted(points, key=lambda point: point[1]) # 按 y 坐标排序 return closest_pair_recursive(px, py)[^1] # 测试代码 if __name__ == "__main__": test_points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)] result = closest_pair(test_points) print(f"The smallest distance is {result}") ``` 上述代码实现了分治法来解决问题的核心逻辑。它首先按照 `x` 和 `y` 的坐标对点进行排序,接着利用递归来逐步缩小范围直到可以应用暴力搜索的部分。最后处理横跨分割线的特殊情况以确保全局最优解被考虑进去。 #### 暴力法解决平面最近点对 虽然暴力法效率较低,但在某些情况下仍然适用。它的基本思路是对每一对点都计算一次它们间的距离,并记录其中最小的那个。 下面是简单的暴力实现版本: ```python def naive_closest_pair(points: List[Tuple[float, float]]) -> float: """ 暴力求解最近点对问题 """ min_distance = float(&#39;inf&#39;) num_points = len(points) for i in range(num_points): for j in range(i + 1, num_points): current_distance = distance(points[i], points[j]) if current_distance < min_distance: min_distance = current_distance return min_distance ``` 此段程序简单明了地展示了如何逐一比较所有组合中的距离值从而得出结论的方法。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值