最近对问题——分治法

问题描述:设p1=(x1,y1),p2=(x2,y2),...,pn=(xn,yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对(二维平面)。

1、蛮力法:直接用欧几里得距离计算即可

#include
#include
#include
using namespace std;
struct In{
	double x;
	double y;
}p[500];
int main(){
	int n;
	double min,d;
	double x1,y1,x2,y2;
	printf("输入n:\n");
	scanf("%d",&n);
	printf("输入%d个点:\n",n);
	for(int i=0;id){
		   min=d;
		   x1=p[i].x;y1=p[i].y;
		   x2=p[j].x;y2=p[j].y;
		}
	}
	printf("输出最近对的距离:\n%lf\n",sqrt(min));
	printf("输出最近对的两个点:\n(%lf,%lf)与(%lf,%lf)\n",x1,y1,x2,y2);
}
/*
5
85.1 52.1 65 85.6 12.6 5.2 2.1 6.1 3 9.64
*/

2、分治法

算法效率取决于划分点m的选取,要遵循平衡子问题的原则;

思想:点(x,y)

首先对所有点s按照x坐标升序排列,选取m为x的中位数;

Closepoints(s):

若只有一个点,return inf;

若只剩两个点,return 欧几里得距离;

若剩下三个点,分别计算两两点距离,比较三个中的最小值,将其返回;

      构造集合s1,s2;使得s1为x坐标小于m,s2为x坐标大于m;

      递归:d1=ClosePoints(s1);d2=ClosePoints(s2);

      d=min(d1,d2);

      构造集合p1,p2;p1为m减s1中点的x坐标的差值不超过d,p2为s2中点的x坐标减m的差值不超过d;

      对p1,p2按照y坐标升序排列;

      对于p1中每一个点,找出其y坐标与p2中点的y坐标差值不超过d的点,计算两点距离为dp;

      return min(d,dp);

注意:p1 p2点因 鸽舍原理 点不会超过6个(有说8个的)

#include
#include 
#include
#include
#include
using namespace std;

/*递归中慎用全局变量(若这些变量涉及到递归传参)*/

struct In{
	double x;
	double y;
};
int cmp(const void *a,const void *b){
	return (*(In*)a).x - (*(In*)b).x;
}
int cmp1(const void*a,const void*b){
	return (*(In*)a).y>(*(In*)b).y?1:-1;
}
double ClosePoint(In s[],int n,In f[]){
	int i,j=0,k=0,t,flag,nk;
	double d1,d2,d,di,dt,m;
    struct In p1[100],p2[100],s1[300],s2[300];
	struct In t1[2],t2[2];
	if(n==1)return 20000;//inf无限大 一个点 
	if(n==2){//两个点 
		f[0]=s[0];f[1]=s[1];
		d=pow(s[0].x-s[1].x,2)+pow(s[0].y-s[1].y,2);
		return d;
	}
	if(n==3){//三个点
		d=pow(s[0].x-s[1].x,2)+pow(s[0].y-s[1].y,2);
		d1=pow(s[0].x-s[2].x,2)+pow(s[0].y-s[2].y,2);
		d2=pow(s[2].x-s[1].x,2)+pow(s[2].y-s[1].y,2);
		if((dm)s2[t++]=s[i];

	d1=ClosePoint(s1,flag,f);
	t1[0]=f[0];t1[1]=f[1];//记录最短距离的位置 
	d2=ClosePoint(s2,t,f);
	t2[0]=f[0];t2[1]=f[1];
	if(d1

 

你可能感兴趣的:(分治法,算法设计与分析,分治法)