1. 程式人生 > >最近點對學習筆記

最近點對學習筆記

long long style lap gis 大於 pan 左右 算法 減少

最近點對算法步驟

1.先把所有點按照橫坐標的關鍵字排序

2.選取中線將點分成2份

3.遞歸的求出左邊部分的最近點距離d1,右邊的最近點距離d2,取d=min(d1,d2)

4.以中線為界,在左右2邊d的範圍內尋找點,看是否存在跨越中線的點距離小於d

我們要註意的就是第四步,本來我們是需要n^2的時間,但是由於我們已經知道了左右的最近點距離,所以我們向左搜和向右搜的範圍就大大減少了,而且,如果存在2個點的在我們搜的左右範圍內,但是其2點的縱坐標之差大於d也可以直接排除了

所以第三步的具體做法就出來啦......

1."刪除"所有到中線距離大於d的點.

2.把一邊平面內的點按照縱坐標排序

3.對於另外一個平面內的點,找到其縱坐標的差在d以內的點,計算距離取min

就是這樣啦

技術分享圖片
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define FOR(i,a,b) for(register int i=a;i<=b;i++)
 4 #define ROF(i,a,b) for(register int i=a;i>=b;i--)
 5 using namespace std;
 6 int n;
 7 const ll N=1000000000000;
 8 int tmpt[200100];
 9 struct ss
10 {
11     double x;double y;
12 }pot[200100
]; 13 int scan() 14 { 15 int as=0,f=1; 16 char c=getchar(); 17 while(c>9||c<0){if(c==-) f=-1;c=getchar();} 18 while(c>=0&&c<=9){as=(as<<3)+(as<<1)+c-0;c=getchar();} 19 return as*f; 20 } 21 bool cmp(ss i,ss j) 22 { 23 return i.x<j.x; 24
} 25 bool cmp2(int i,int j) 26 { 27 return pot[i].y<pot[j].y; 28 } 29 double dis(int i,int j) 30 { 31 double f=sqrt(double((pot[i].x-pot[j].x)*(pot[i].x-pot[j].x)+(pot[i].y-pot[j].y)*(pot[i].y-pot[j].y))); 32 return f; 33 } 34 double par(int l,int r) 35 { 36 // cout<<"y"<<endl; 37 double d=N; 38 if(l==r) return d; 39 if(l+1==r) return dis(l,r); 40 int mid=(l+r)>>1;//除以2 41 double d1=par(l,mid); 42 double d2=par(mid+1,r); 43 d=min(d1,d2); 44 int k=0; 45 FOR(i,l,r) 46 { 47 if(abs(pot[i].x-pot[mid].x)<=d) 48 { 49 tmpt[++k]=i;//保存位置 50 } 51 } 52 sort(tmpt+1,tmpt+k+1,cmp2); 53 FOR(i,1,k) 54 { 55 FOR(j,i+1,k) 56 { 57 if(pot[tmpt[j]].y-pot[tmpt[i]].y>=d) break; 58 double d3=dis(tmpt[i],tmpt[j]); 59 d=min(d,d3); 60 } 61 } 62 return d; 63 } 64 int main() 65 { 66 // freopen("copy.in","r",stdin); 67 // freopen("copy.out","w",stdout); 68 n=scan(); 69 FOR(i,1,n) 70 { 71 scanf("%lf%lf",&pot[i].x,&pot[i].y); 72 } 73 sort(pot+1,pot+n+1,cmp); 74 double h=par(1,n); 75 printf("%.4lf",h);//求1~n的最近點對 76 return 0; 77 }
代碼在這裏

最近點對學習筆記