题意:求平面上n个点中最短的两个点的距离
思想:分治法
1:暴力枚举法一般都超时啦,复杂度为O(n^2)
2:分治法
将n个点划分为左右两部分,为使两边尽量均匀,一般以所谓点的横坐标的平均值为界。则最段点对要么在左边点中,要么在右边点中,要么横跨分界线。取左右点集合中最小值,再以它为范围,以分界线为中轴划出一部分区域,则横跨分界线的情况只可能在这部分区域中。最后取三者最小值即可。
对于左右两部分,则是简单的子问题,直接递归调用即可,而对于中间部分,由于区域被划小了,直接枚举一个个比较。
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <algorithm> 4 using namespace std; 5 #define MAXN 10000 6 const int INF = 9999999; 7 8 struct node 9 { 10 double x, y; 11 }p[MAXN], ym[MAXN]; 12 13 int n; 14 15 int cmpx(const node a, const node b) 16 { 17 return a.x < b.x; 18 } 19 20 int cmpy(const node a, const node b) 21 { 22 return a.y < b.y; 23 } 24 25 double dist(node a, node b) 26 { 27 return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); 28 } 29 30 double getmind(node *p, int l, int r) 31 { 32 if(l == r) return INF; //只有一个点 33 if(l+1 == r) return dist(p[l], p[r]);//只有两个点 34 int mid = (l+r)/2; 35 double ans = min(getmind(p, l,mid), getmind(p, mid+1, r)); 36 int yn = 0; 37 for(int i = l; i <= r ; i++) 38 { 39 if(fabs(p[i].x - p[mid].x) <= ans)//满足这样的才有比较的意义 40 { 41 ym[yn++] = p[i]; 42 } 43 } 44 sort(ym, ym+yn, cmpy); //预排序 45 for(int i = 0; i < yn; i++) 46 { 47 for(int j = i+1; j < yn; j++) 48 { 49 if((ym[j].y - ym[i].y) >= ans) break; //if(|y1-y2| >= ans) break; 50 ans = min(ans, dist(ym[i], ym[j])); 51 } 52 } 53 return ans; 54 } 55 56 int main() 57 { 58 int T; 59 scanf("%d", &T); 60 while(T--) 61 { 62 scanf("%d", &n); 63 for(int i = 0; i < n; i++) 64 { 65 scanf("%lf%lf", &p[i].x, &p[i].y); 66 } 67 sort(p, p+n, cmpx); 68 double ans = getmind(p, 0,n-1); 69 printf("%.3f\n", ans); 70 } 71 return 0; 72 }
变形:最短点对分别属于两个点集
接近方法:稍稍改变,标记两个点集,若两点属于同一个点集,则将距离设为最大值
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <algorithm> 4 using namespace std; 5 #define MAXN 100010 6 const int INF =999999; 7 8 struct node 9 { 10 double x, y; 11 int f;//用来标记两个点集 12 }p[MAXN], ym[MAXN]; 13 14 int n; 15 16 int cmpx(const node a, const node b) 17 { 18 return a.x < b.x; 19 } 20 21 int cmpy(const node a, const node b) 22 { 23 return a.y < b.y; 24 } 25 26 double dist(node a, node b) 27 { 28 if(a.f * b.f > 0) return INF; 29 return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); 30 } 31 32 double getmind(node *p, int l, int r) 33 { 34 if(l == r) return INF; //只有一个点 35 if(l+1 == r) return dist(p[l], p[r]); //只有两个点 36 int mid = (l+r)/2; 37 double ans = min(getmind(p, l,mid), getmind(p, mid+1, r)); 38 int yn = 0; 39 for(int i = l; i <= r ; i++) //divide 40 { 41 if(fabs(p[i].x - p[mid].x) <= ans) 42 { 43 ym[yn++] = p[i]; 44 } 45 } 46 sort(ym, ym+yn, cmpy); //预排序 47 for(int i = 0; i < yn; i++) 48 { 49 for(int j = i+1; j < yn; j++) 50 { 51 if(ym[j].y - ym[i].y >= ans) break; //if(|y1-y2| >= ans) break; 52 ans = min(ans, dist(ym[i], ym[j])); 53 } 54 } 55 return ans; 56 } 57 58 59 int main() 60 { 61 int T; 62 scanf("%d", &T); 63 while(T--) 64 { 65 scanf("%d", &n); 66 for(int i = 0; i < n; i++) 67 { 68 scanf("%lf%lf", &p[i].x, &p[i].y); 69 p[i].f = 1; 70 } 71 for(int i = n; i < 2*n ; i++) 72 { 73 scanf("%lf%lf", &p[i].x, &p[i].y); 74 p[i].f = -1; 75 } 76 sort(p, p+2*n, cmpx); 77 double ans = getmind(p, 0, 2*n-1); 78 printf("%.3f\n", ans); 79 } 80 return 0; 81 }
浙公网安备 33010602011771号