poj 3714 杭电 1007(最近点对)

本文介绍了一种使用分治算法解决最近点对问题的方法,并提供了两段完整的C++代码实现。该算法通过比较各点之间的欧氏距离来找到距离最近的两个点。文章涉及了数据结构的设计、排序算法的应用及分治思想的具体实现。

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

杭电 1007  最近点对,分治
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;

#define N 100010

struct POINT
{
	double x,y;
}point[N],ym[1000];

bool cmpx(POINT a,POINT b) 
{
	return a.x<b.x;
}

bool cmpy(POINT a,POINT b)
{
	return a.y<b.y;
}
double distance1(POINT a,POINT b)  //两点之间距离
{
	return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
	
}
double min(double x,double y) 
{
	if(x<y) return x;
	return y;
}
double closedistance(POINT * p,int left,int right)
{
	int i,j,mid,yn;
	double ans;
  	if(right==left+1)
        return distance1(p[left],p[right]);
	if(right==left+2)
		return min( distance1(p[left],p[left+2]),min(distance1(p [left],p[left+1]),distance1(p[left+1],p[left+2])) );
     mid=(left+right)>>1;
     ans=min(closedistance(p,left,mid),closedistance(p,mid+1,right));  //找出两边的最小值, 与中间点对可能形成的最小值找出最小值
     yn=0;
    for( i=left;i<=right;i++)
		if(p[i].x>=p[mid].x-ans && p[i].x<=p[mid].x+ans)
			ym[yn++]=p[i];
		
		std::sort(ym,ym+yn,cmpy);
		for(i=0;i<yn;i++)
			for( j=i+1;j<yn;j++)
			{
				if(ym[j].y-ym[i].y>=ans)
					break;
				ans=min(ans,distance1(ym[i],ym[j]));
			}
	 return ans;	
};

int main()
{
	int n,i;
	while(scanf("%d",&n)!=EOF)
	{
		if(n<=0)break;
		for( i=0;i<n;i++)
			scanf("%lf%lf",&point[i].x,&point[i].y);
		std::sort(point,point+n,cmpx);
       	printf("%.2lf\n",closedistance(point,0,n-1)/2);
	}
	return 0;
}


poj  3714

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;

#define N 100010

struct POINT
{
	double x,y;
	int flag;
}point[N],ym[N];

bool cmpx(POINT a,POINT b)
{
	return a.x<b.x;
}

bool cmpy(POINT a,POINT b)
{
	return a.y<b.y;
}
double distance1(POINT a,POINT b)
{
	if(a.flag!=b.flag)
		return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
	return 1e50;
}
double min(double x,double y)
{
	if(x<y) return x;
	return y;
}
double closedistance(POINT * p,int left,int right)
{
	int i,j,mid,yn;
	double ans;
	if(right==left+1)
        return distance1(p[left],p[right]);
	if(right==left+2)
		return min( distance1(p[left],p[left+2]),min(distance1(p[left],p[left+1]),distance1(p[left+1],p[left+2])) );
	mid=(left+right)>>1;
	ans=min(closedistance(p,left,mid),closedistance(p,mid+1,right));
	yn=0;
    for( i=left;i<=right;i++)
		if(p[i].x>=p[mid].x-ans && p[i].x<=p[mid].x+ans)
			ym[yn++]=p[i];
		
		std::sort(ym,ym+yn,cmpy);
		for(i=0;i<yn;i++)
			for( j=i+1;j<yn;j++)
			{
				if(ym[j].y-ym[i].y>=ans)
					break;
				ans=min(ans,distance1(ym[i],ym[j]));
			}
	return ans;	
};

int main()
{
	int t,i,n;
	scanf("%d",&t);
	
	while(t--)
	{
        scanf("%d",&n);
		
		for(i=0;i<n;i++)
		{
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].flag=0;
		}
        for(i=n;i<2*n;i++)
		{
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].flag=1;
		}
		n<<=1;
		std::sort(point,point+n,cmpx);
		
		printf("%.3lf\n",closedistance(point,0,n-1));
	}
	
	return 0;	
}


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值