最近對問題(二維平面上的點)分治法
阿新 • • 發佈:2018-12-18
#include<iostream> #include<ctime> #include<cmath> #include<algorithm> using namespace std; #define number 1000000 typedef struct point { float x,y; }point;//定義二維點point,橫縱座標範圍均為【-100,100】 void setpoints(point *points,int num) { //隨機生成兌點陣列points中的二維點, srand(unsigned(time(NULL))); for(int i=0;i<num;i++) { points[i].x=(rand()%20000)/100.0-100;//調整rand,使得橫座標範圍在【-100,100】 points[i].y=(rand()%20000)/100.0-100; } } float Distance(point a,point b) { //計算平面上任意兩點之間的距離 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } bool CmpX(point a,point b) { //自定義排序 return a.x<b.x; } float ClosestPair(point points[],int num,point &a,point &b) { float distance; float d1,d2; int i=0,j=0,k=0; point a1,b1,a2,b2; if(num<2) return number; if(num==2) { a=points[0]; b=points[1]; distance=Distance(points[0],points[1]); } else { point *s1=new point[num]; //開闢兩個子集 point *s2=new point[num]; sort(points,points+num,CmpX); float mid=points[(num-1)/2].x; for(i=0;i<num/2;i++) s1[i]=points[i]; for(j=0,i=num/2;i<num;i++) s2[j++]=points[i]; d1=ClosestPair(s1,num/2,a1,b1); d2=ClosestPair(s2,num-num/2,a2,b2); if(d1<d2) { distance=d1; a=a1; b=b1;} else { distance=d2; a=a2; b=b2;} //求解跨分割線並在δ×2δ區間內的最近點對 point *s=new point[num]; for(i=0,k=0;i<num;i++) if(abs(points[i].x-mid)<=distance) s[k++]=points[i]; for(i=0;i<k;i++) for(j=i+1;j<=i+7&&j<k;j++) { if(Distance(s[i],s[j])<distance) {//如果跨分割線的兩點距離小於已知最小距離,則記錄該距離 distance=Distance(s[i],s[j]); a=s[i]; b=s[j]; } } } return distance; } int main() { int N; point a,b; float d; cout<<"請輸入二維點個數:"; cin>>N; if(N<2) cout<<"請輸入大於或等於2的點個數!"<<endl; else { point *points=new point[N]; setpoints(points,N); d=ClosestPair(points,N,a,b); cout<<"隨機生成的"<<N<<"個二維點如下(按橫座標排序後的點對):"<<endl; for(int i=0;i<N;i++) { cout<<"("<<points[i].x<<","<<points[i].y<<")"<<endl; } cout<<endl<<"最近點對為:"<<"("<<a.x<<","<<a.y<<")和"<<"("<<b.x<<","<<b.y<<")"<<endl<<"最近點對距離為:"<<d<<endl; } return 0; }