平面点集最接近点对问题怎么做

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平面点集最接近点对问题怎么做相关的知识,希望对你有一定的参考价值。

#include<cmath>
#include<cstdlib>
#include<fstream>
#include<iostream>

usingnamespacestd;
structPoint

floatx;
floaty;
;
structPoint1

intIndex;
floatx;
floaty;
;
voidInput(PointX[],intN);
voidSort1(PointX[],intN);
voidSort2(Point1Y[],intN);
voidSpot(PointX[],intn,Point&a,Point&b,float&d);
voidFind(PointX[],Point1Y[],intlow,inthigh,Point&a,Point&b,float&d);
floatdist(Pointa,Pointb);
intmain(intargc,char*argv[])

intN;
cout<<"请输入点的个数\n";
cin>>N;
PointX[N];
Input(X,N);
Pointa,b;
floatd=0;
Spot(X,N,a,b,d);
cout<<"最短距离是"<<d<<endl;
system("PAUSE");
returnEXIT_SUCCESS;

voidInput(PointX[],intN)

ifstreamIn("点集数据2.txt");
for(inti=0;i<N;i++)

In>>X[i].x;
In>>X[i].y;
cout<<"第"<<i+1<<"个点:"<<X[i].x<<"."<<X[i].y<<endl;


voidSort1(PointX[],intN)

Pointtemp;
for(inti=0;i<N;i++)
for(intj=0;j<N-i-1;j++)
if(X[j].x>X[j+1].x)

temp=X[j];
X[j]=X[j+1];
X[j+1]=temp;

cout<<"按X轴排序后是--------\n";
for(inti=0;i<N;i++)
cout<<X[i].x<<"."<<X[i].y<<endl;
cout<<"====================================\n";

voidSort2(Point1Y[],intN)

Point1temp;
for(inti=0;i<N;i++)
for(intj=0;j<N-i-1;j++)
if(Y[j].y>Y[j+1].y)

temp=Y[j];
Y[j]=Y[j+1];
Y[j+1]=temp;

cout<<"按Y轴排序后是--------\n";
for(inti=0;i<N;i++)
cout<<Y[i].x<<"."<<Y[i].y<<endl;
cout<<"====================================\n";

voidSpot(PointX[],intn,Point&a,Point&b,float&d)

if(n<2)

d=0;
return;

else

Sort1(X,n);
Point1*Y=newPoint1[n];
for(inti=0;i<n;i++)

Y[i].Index=i;
Y[i].x=X[i].x;
Y[i].y=X[i].y;

Sort2(Y,n);
Find(X,Y,0,n-1,a,b,d);
d=sqrt(d);
deleteY;
return;

return;

voidFind(PointX[],Point1Y[],intlow,inthigh,
Point&a,Point&b,float&d)

inti,j,k,m;
Pointal,bl,ar,br;
floatdl,dr;
if((high-low)==1)

a=X[low];
b=X[low+1];
d=dist(X[low],X[low+1]);
return;

else

if((high-low)==2)

dl=dist(X[low],X[low+1]);
dr=dist(X[low],X[low+2]);
d=dist(X[low+1],X[low+2]);
if((dl<=dr)&&(dl<=d))

a=X[low];
b=X[low+1];
d=dl;

else

if(dr<=d)

a=X[low];
b=X[low+2];
d=dr;

else

a=X[low+1];
b=X[low+2];



else

Point1*SL=newPoint1[(high-low)/2+1];
Point1*SR=newPoint1[(high-low)/2];
m=(high-low)/2+low;
j=k=0;
for(i=0;i<=high;i++)

if(Y[i].Index<=m)
SL[j++]=Y[i];
else
SR[k++]=Y[i];

Find(X,SL,low,m,al,bl,dl);
Find(X,SR,m+1,high,ar,br,dr);
if(dl<dr)

a=al;
b=bl;
d=dl;

else

a=ar;
b=br;
d=dr;

Point*z=newPoint[high-low+1];
k=0;
for(i=0;i<=high-low;i++)
if(fabs(X[m].x-Y[i].x)<d)

z[k].x=Y[i].x;
z[k++].y=Y[i].y;

for(i=0;i<k;i++)
for(j=i+1;(j<k)&&((z[j].y-z[i].y)<d);j++)

dl=dist(z[i],z[j]);
if(dl<d)

a=z[i];
b=z[j];
d=dl;


delete[]SL;
delete[]SR;
delete[]z;



floatdist(Pointa,Pointb)

floatdx=0,dy=0;
cout<<"a:"<<a.x<<"."<<a.y;
cout<<"b:"<<b.x<<"."<<b.y;
dx=a.x-b.x;
dy=a.y-b.y;
cout<<"距离是"<<sqrt(dx*dx+dy*dy)<<endl;
return(dx*dx+dy*dy);

上面时我的代码,在7,8,9个点时要出错啊,老师要求用分治啊,帮帮忙啊,要么改下我的代码,要么自己写一个啊,大虾们.....好的++分哦

参考技术A 你那个已经是分治法了...
但是似乎有点问题
给你贴一份我的代码.
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
class point

public:
double x,y;
int pos;
point()x=y=pos=0;
point(const point &s)x=s.x;y=s.y;pos=s.pos;
bool operator > (const point &s)

return x>s.x?true:false;

bool operator < (const point &s)

return y<s.y?true:false;

;
point x[100001],y[100001],z[100001];
int n;
int cmpx(const void *t1,const void *t2)

return (*(point *)t1).x>(*(point *)t2).x?1:-1;

int cmpy(const void *t1,const void *t2)

return (*(point *)t1).y>(*(point *)t2).y?1:-1;

inline double min(double t1,double t2)

return (t1<t2)?t1:t2;

void Merge(point *t1,point *t2,int st,int ed)

int p1=st;
int p2=(st+ed)/2+1;
int p3=st;
while(p1<=(st+ed)/2&&p2<=ed)

if(t2[p1]<t2[p2])t1[p3++]=t2[p1++];
else t1[p3++]=t2[p2++];

while(p1<=(st+ed)/2)
t1[p3++]=t2[p1++];
while(p2<=ed)
t1[p3++]=t2[p2++];

inline double dist(point &t1,point &t2)

double dx=t1.x-t2.x;
double dy=t1.y-t2.y;
return sqrt(dx*dx+dy*dy);

void divide(point *x1,point *y1,point *z1,int st,int ed,int &p1,int &p2,double &best)

if(ed-st==1)

p1=st;
p2=ed;
best=dist(x[p1],x[p2]);
return;

if(ed-st==2)

double d1=dist(x[st],x[st+1]);
double d2=dist(x[st+1],x[ed]);
double d3=dist(x[st],x[ed]);
double d=min(d1,d2);
d=min(d,d3);
if(d==d1)

p1=st;
p2=st+1;

else if(d==d2)

p1=st+1;
p2=ed;

else

p1=st;
p2=ed;

best=d;
return;

int mid=(st+ed)/2;
int cnt=st;
int cnt1=mid+1;
for(int i=st;i<=ed;i++)
if(y1[i].pos>mid)z1[cnt1++]=y[i];
else z1[cnt++]=y[i];
int p12,p22;
double bestd;
divide(x1,z1,y1,st,mid,p12,p22,bestd);
int p11,p21;
double bestd1;
divide(x1,z1,y1,mid+1,ed,p11,p21,bestd1);
if(bestd1<bestd)p12=p11;p22=p21;bestd=bestd1;
p1=p12;
p2=p22;
best=bestd;
Merge(y1,z1,st,ed);
int l=st;
for(int i=st;i<=ed;i++)
if(abs(x1[i].x-x1[mid].x)<bestd)

z1[l++]=x1[i];
z1[l-1].pos=i;

for(int i=st;i<l;i++)
for(int j=i+1;j<l;j++)
if(dist(z1[i],z1[j])<bestd)

p1=z1[i].pos;
p2=z1[j].pos;
best=dist(z1[i],z1[j]);


int main(void)

FILE *fin=fopen("input.txt","r");
FILE *fout=fopen("output.txt","w");
fscanf(fin,"%d",&n);
for(int i=0;i<n;i++)
fscanf(fin,"%lf %lf",&x[i].x,&x[i].y);
qsort(x,n,sizeof(point),cmpx);
for(int i=0;i<n;i++)

y[i].x=x[i].x;
y[i].y=x[i].y;
y[i].pos=i;

qsort(y,n,sizeof(point),cmpy);
for(int i=0;i<n;i++)
x[y[i].pos].pos=i;
int p1,p2;
double bestd;
divide(x,y,z,0,n-1,p1,p2,bestd);
fprintf(fout,"%.3lf\n",bestd);
fclose(fin);
fclose(fout);
return 0;

还有,你那个代码应该会爆Access Violation的才对...
你可以对比一下咱们的代码.
(p.s.我的代码在Vijos上P1012 Accepted.)本回答被提问者采纳

以上是关于平面点集最接近点对问题怎么做的主要内容,如果未能解决你的问题,请参考以下文章

检查平面点的哪一侧

谁知道如何搜索平面点集的边界?

平面最接近点对问题(分治法)

平面最接近点对

ZZNUOJ_用C语言编写程序实现1183:平面点排序(结构体专题)(附完整源码)

ZZNUOJ_用C语言编写程序实现1184:平面点排序(结构体专题)(附完整源码)