poj3714 Raid

哈,就这样水过去了??

不科学呀。

好吧,平面最近点对(伪)。

就是一个二分的事:

1.以x排序。

2.二分,递归求解。

具体来讲,主要难在如何求 横跨两个区域的最近点对 这一环节。

那么是这样做的:首先我们会有个ans是左右的最小值对吧。

我们只考虑在划分线左右两边不超过ans的那些点(即为[_l, _r])

然后把这些点暴力求解即可AC按照y排序,这样的情况下,再只考虑与一个点上下不超过ans的那些点即可......

那么下面是我的暴力版写法:

 1 /// poj 3714
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long LL;
 8 const int N = 100010;
 9 const double INF = (double)(0x7f7f7f7f);
10 
11 struct Point {
12     LL x, y;
13     bool f;
14     bool operator < (const Point &k) const {
15         return x < k.x;
16     }
17 }p[N << 1];
18 
19 inline double dis(int i, int j) {
20     return sqrt((double)((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y)));
21 }
22 
23 double twsolve(int l, int r) {
24     if(l == r) return INF;
25     int mid = (l + r) >> 1;
26     double k = min(twsolve(l, mid), twsolve(mid + 1, r));
27     int _l, _r;
28     for(_l = mid; _l >= l; _l--) {
29         if(p[_l].x <= p[mid + 1].x - k) {
30             break;
31         }
32     }
33     for(_r = mid + 1; _r <= r; _r++){
34         if(p[_r].x >= p[mid].x + k) {
35             break;
36         }
37     }
38     if(_l < l) _l = l;
39     if(_r > r) _r = r;
40     double ans = k;
41     for(int i = _l; i <= mid; i++) {
42         for(int j = mid + 1; j <= _r; j++) {
43             if(!(p[i].f ^ p[j].f)) continue;
44             ans = min(ans, dis(i, j));
45         }
46     }
47     return ans;
48 }
49 
50 int main() {
51     int T, n;
52     scanf("%d", &T);
53     while(T--) {
54         scanf("%d", &n);
55         for(int i = 1; i <= n; i++) {
56             scanf("%I64d %I64d", &p[i].x, &p[i].y);
57             p[i].f = 0;
58 
59         }
60         for(int i = 1; i <= n; i++) {
61             scanf("%I64d %I64d", &p[i + n].x, &p[i + n].y);
62             p[i + n].f = 1;
63         }
64         sort(p + 1, p + (n << 1) + 1);
65         printf("%.3lf\n", twsolve(1, n << 1));
66         //cout << twsolve(1, n << 1) << endl;
67     }
68     return 0;
69 }
AC代码

附赠数据生成器:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<ctime>
 4 using namespace std;
 5 int main()
 6 {
 7     freopen("in.in","w",stdout);
 8     srand(time(0));
 9     printf("1\n");
10     int n = rand() % 100000 + 1;
11     printf("%d\n", n);
12     n = n << 1;
13     for(int i = 1; i <= n; i++) {
14         printf("%d %d\n", rand() % 1000010 + 1, rand() % 1000010 + 1);
15     }
16     return 0;
17 }
数据生成器

猜你喜欢

转载自www.cnblogs.com/huyufeifei/p/9029793.html