问题:
对$n$个不同的数构成的数组$A[1..n]$进行排序,其中$n=2^k$。
解析:
分治思想,对于每个点堆,分成l和r两个点集,分别求每个点集中点的最近对。三种情况:
①$ l = r $:只有一个点,返回 $inf$
②$l = r – 1$:两个点,返回两个点的点距。
③$l = r – 2$:三个点,计算两两点之间的距离,返回最小值。
④超过三个点,则分成两个部分,递归集合最小点距。
已知两个集合内的最小点距,把与中点x距离小于最小点距的点放入容器中。
根据y排序,对于每两个y距离小于最小点距的两个点求距离,更新最小点距。
设计(核心代码):
1 double getMin(int l, int r)
2 {
3 if (l == r) return inf;
4 if (r - l == 1) return dis(p[r], p[l]);
5 if (r - l == 2)
6 {
7 double d1, d2, d3;
8 d1 = dis(p[l], p[l + 1]);
9 d2 = dis(p[l], p[r]);
10 d3 = dis(p[l + 1], p[r]);
11 return min(d1, min(d2, d3));
12 }
13 int mid = l + r >> 1;
14 double dl, dr;
15 dl = getMin(l, mid);
16 dr = getMin(mid + 1, r);
17 double res = min(dl, dr);
18 vector<int>vec;
19 for (int i = l; i <= mid; ++i)
20 {
21 if (p[mid + 1].x - p[i].x <= res) vec.push_back(i);
22 }
23 for (int i = mid + 1; i <= r; ++i)
24 {
25 if (p[i].x - p[mid].x <= res) vec.push_back(i);
26 }
27 sort(vec.begin(), vec.end(), cmp2);
28 for (int i = 0; i < vec.size(); ++i)
29 {
30 for (int j = i + 1; j < vec.size(); ++j)
31 {
32 if (p[vec[j]].y - p[vec[i]].y <= res)
33 {
34 res = min(res, dis(p[vec[i]], p[vec[j]]));
35 }
36 else break;
37 }
38 }
39 return res;
40
41 }
分析:
复杂度:$O(nlogn)$。
源码:
https://github.com/Big-Kelly/Algorithm
1 //#include<bits/stdc++.h> 2 #include <set> 3 #include <map> 4 #include <stack> 5 #include <cmath> 6 #include <queue> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 14 #define ll long long 15 #define pll pair<ll,ll> 16 #define pii pair<int,int> 17 #define bug printf("********* ") 18 #define FIN freopen("input.txt","r",stdin); 19 #define FON freopen("output.txt","w+",stdout); 20 #define IO ios::sync_with_stdio(false),cin.tie(0) 21 #define ls root<<1 22 #define rs root<<1|1 23 #define Q(a) cout<<a<<endl 24 25 using namespace std; 26 const int inf = 0x3f3f3f3f; 27 const ll Inf = 1e18 + 7; 28 const int maxn = 1e4 + 5; 29 const int mod = 1e9 + 7; 30 31 ll gcd(ll a, ll b) 32 { 33 return b ? gcd(b, a % b) : a; 34 } 35 36 ll lcm(ll a, ll b) 37 { 38 return a / gcd(a, b) * b; 39 } 40 41 ll read() 42 { 43 ll p = 0, sum = 0; 44 char ch; 45 ch = getchar(); 46 while (1) 47 { 48 if (ch == '-' || (ch >= '0' && ch <= '9')) 49 break; 50 ch = getchar(); 51 } 52 53 if (ch == '-') 54 { 55 p = 1; 56 ch = getchar(); 57 } 58 while (ch >= '0' && ch <= '9') 59 { 60 sum = sum * 10 + ch - '0'; 61 ch = getchar(); 62 } 63 return p ? -sum : sum; 64 } 65 66 struct node 67 { 68 int x, y; 69 }p[maxn]; 70 71 bool cmp(const node& a, const node& b) 72 { 73 return a.x < b.x; 74 } 75 76 bool cmp2(const int& a, const int& b) 77 { 78 return p[a].y < p[b].y; 79 } 80 81 double dis(const node& a, const node& b) 82 { 83 double x = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); 84 return sqrt(x); 85 } 86 87 int n; 88 89 double getMin(int l, int r) 90 { 91 if (l == r) return inf; 92 if (r - l == 1) return dis(p[r], p[l]); 93 if (r - l == 2) 94 { 95 double d1, d2, d3; 96 d1 = dis(p[l], p[l + 1]); 97 d2 = dis(p[l], p[r]); 98 d3 = dis(p[l + 1], p[r]); 99 return min(d1, min(d2, d3)); 100 } 101 int mid = l + r >> 1; 102 double dl, dr; 103 dl = getMin(l, mid); 104 dr = getMin(mid + 1, r); 105 double res = min(dl, dr); 106 vector<int>vec; 107 for (int i = l; i <= mid; ++i) 108 { 109 if (p[mid + 1].x - p[i].x <= res) vec.push_back(i); 110 } 111 for (int i = mid + 1; i <= r; ++i) 112 { 113 if (p[i].x - p[mid].x <= res) vec.push_back(i); 114 } 115 sort(vec.begin(), vec.end(), cmp2); 116 for (int i = 0; i < vec.size(); ++i) 117 { 118 for (int j = i + 1; j < vec.size(); ++j) 119 { 120 if (p[vec[j]].y - p[vec[i]].y <= res) 121 { 122 res = min(res, dis(p[vec[i]], p[vec[j]])); 123 } 124 else break; 125 } 126 } 127 return res; 128 129 } 130 131 int main() 132 { 133 scanf("%d", &n); 134 for (int i = 1; i <= n; ++i) 135 { 136 scanf("%d %d", &p[i].x, &p[i].y); 137 } 138 sort(p + 1, p + 1 + n, cmp); 139 printf("%.2f ", getMin(1, n)); 140 }