分治算法應用-最近點對的最小距離-hdu 1007 Quoit Design


題目描述

  給出二維平面上的n個點,求其中最近的兩個點的距離的一半。

  輸入包含多組數據,每組數據第一行為n,表示點的個數;接下來n行,每行一個點的坐標。當n為0時表示輸入結束,每組數據輸出一行,為最近的兩個點的距離的一半。

  輸入樣例:

    2

    0 0

    1 1

    2

    1 1

    1 1

    3

    -1.5 0

    0 0

    0 1.5

    0

  輸出樣例:

    0.71

    0.00

    0.75

題目解析:

  采用分治的思想,把n個點按照x坐標進行排序,以坐標mid為界限分成左右兩個部分,對左右兩個部分分別求最近點對的距離,然后進行合並。對於兩個部分求得的最近距離d,合並過程中應當檢查寬為2d的帶狀區間是否有兩個點分屬於兩個集合而且距離小於d,最多可能有n個點,合並時間最壞情況下是O(n^2).但是,左邊和右邊中的點具有以下稀疏的性質,對於左邊中的任意一點,右邊的點必定落在一個d*2d的矩形中,且最多只需檢查6個點(鴿巢原理),這樣,先將帶狀區間的點按照y坐標進行排序,然后線性掃描,這樣合並的時間復雜度為O(nlogn)。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 
 7 double MAX=1e10; //定義的最大距離,以在只有一個點的時返回無窮大
 8 int a,b;   //用來記錄下標,與題無關
 9 struct Node{
10     double x,y;
11     int key;   //關鍵碼,可有可無,與ab有關
12 };
13 
14 Node ar[100005],br[100005];
15 
16 bool cmpx(Node a,Node b){return a.x<b.x;}  //x坐標升序
17 bool cmpy(Node a,Node b){return a.y<b.y;}  //y坐標升序
18 double min(double a,double b){return a<b?a:b;}  //返回最小值
19 double dis(Node a,Node b){return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));}  //返回點與點之間的距離
20 
21 double cal(int s,int e)  //s、e用來表示當前處理的數組中的下標位置
22 {
23     int mid,i,j,tail=0;   //mid表示數組中間的位置下標 ,tail作為計數變量,是用來br數組存儲標號的
24     double d;   //d表示點對之間的距離
25     if(s==e) return MAX;   //如果只有一個點
26     mid=(s+e)/2;
27     d=min(cal(s,mid),cal(mid+1,e));  //遞歸求出左右兩邊的最小距離
      //下面是求是否存在左邊的點到右邊某點的距離小於d的點,或者是否存在在右邊的點到左邊某點的距離小於d的點,若是存在,必定處於一個d*2d的矩形中
28 for(i=mid;i>=s&&ar[mid].x-ar[i].x<d;i--){ //篩選左邊的點,在中間位置左側d以內的點 29 br[tail++]=ar[i]; 30 } 31 32 for(i=mid+1;i<e&&ar[i].x-ar[mid].x<d;i++) //同上,篩選右邊的點 33 { 34 br[tail++]=ar[i]; 35 } 36 sort(br,br+tail,cmpy); //對矩形內的點按照y坐標進行排序 37 for(i=0;i<tail;i++){              //枚舉矩形內點對之間的距離                    38 for(j=i+1;j<tail&&br[j].y-br[i].y<d;j++){ 39 if(d>dis(br[i],br[j])){ //更新點的值 40 //a=min(br[i].key,br[j].key); 41 //b=br[i].key+br[j].key-a; 42 d=min(d,dis(br[i],br[j])); 43 } 44 } 45 } 46 return d; //返回最小的點對之間的距離 47 } 48 49 int main() 50 { 51 52 int n; 53 while(cin>>n&&n){ 54 for(int i=0;i<n;i++){ 55 ar[i].key=i+1; //關鍵碼賦值 56 scanf("%lf %lf",&ar[i].x,&ar[i].y); 57 } 58 sort(ar,ar+n,cmpx); //按x對ar排序 59 double d=cal(0,n); 60 printf("%.2lf\n",d/2.0); 61 } 62 return 0; 63 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM