【套圈问题】最近点对问题的探讨

最近点对问题算法

最近点对问题是一种很典型的递归分治算法,我们知道,递归分治的核心步骤就是



这里我们怎么分,怎么治,怎么合,便是一个值得探讨的问题。
先给出应用的结构体和主函数:

struct node{
	double x;
	double y;
}X[100001],tmp[100001];
int main()
{
	int N,i;
	scanf("%d",&N);
	for(i = 0; i < N; i++)
	{
		double x,y;
		scanf("%lf%lf",&x,&y);
		X[i].x = x;
		X[i].y = y;
	}
	qsort(X,N,sizeof(X[0]),comp_x);//先将点对按x的大小排序
	double ans = closest(0,N-1);
	printf("输入点对中距离最近的两点距离为%.2f",ans);
}

本算法的核心在于closest函数,通过这个函数的递归分治,可以大事化小,小事化更小。

double closest(int l, int r)
{
	if(l + 1 == r)
		return distance(X[l],X[r]);
	if(l + 2 == r)
		return min(distance(X[l],X[l+1]),min(distance(X[l+1],X[r]),distance(X[l],X[r])));
	//只要输入点对大于2,就“分”:
	int mid = (l + r) / 2;
	double left_d = closest(l,mid);
	double right_d = closest(mid + 1,r);
	d = min(left_d,right_d);//从这一步开始“合”:
	//具体的合的过程即是把中间处的最小距离和左右求得的最小距离相比较
	int i,j,a = 0;
	for(i = l; i <= r; i++)
	{
		if(fabs(X[i].x - X[mid].x) < d)//把符合初步条件(横坐标与中位线距离小于d的点挖出来,存储在tmp结构体中)
		{
			tmp[a].x = X[i].x;
			tmp[a++].x = X[i].y;
		}
	}
	qsort(tmp,a,sizeof(tmp[0]),comp_y);//按照y的大小对tmp结构进行排序
	for(i = 0; i < a; i++)
	{
		for(j = i + 1; j < a; j++)//这里之所以敢用两层循环,是因为循环中的break,根据“鸽巢原理/抽屉原理”,一次我们最多找8个点就会break掉了,所以敢放心地用嵌套两层循环
		{
			if(tmp[j].y - tmp[i].y >= d)
				break;
			d = min(d,distance(tmp[i],tmp[j]));
		}
	}
	return d;
}

具体的原理就是分治合,分治原理的算法就是要弄清楚这样的分治合过程。
---------------------------------------分割线----------------------------------------------
最后补充一下两个快排的comp函数:

int comp_x(const void *a, const void *b)
{
	return (* (node *)a).x > (* (node *)b).x;
}
int comp_y(const void *a, const void *b)
{
	return (* (node *)a).y > (* (node *)b).y;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值