突发奇想,用双线程似乎可以优化一些暴力
比如说平面最近点对这个题目,把点复制成2份
一份按照x排序,一份按照y排序
然后双线程暴力处理,一份处理x,一份处理y
如果数据利用x递减来卡,那么由于双线程,它卡不住y
如果数据利用y递减来卡,那么卡不住x
这样暴力n^2就可以过了
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; struct P { int id; double x, y; bool operator <(const P& B)const { return x < B.x; } }p[100050], p2[100050]; bool cmp(const P &A, const P &B) { return A.y < B.y; } double dis(P &A, P &B) { return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y); } int main() { int n; while(cin>>n) { if(n == 0) break; double d = 1e8; for(int i = 1; i <= n; i++) scanf("%lf %lf", &p[i].x, &p[i].y), p2[i].x = p[i].x, p2[i].y = p[i].y; sort(p2+1, p2+1+n, cmp); sort(p+1, p+1+n); int tot1 = 0, tot2 = 100; for(int i1 = 2, i2 = 2, li1 = 1, li2 = 1; i1 <= n && i2 <= n; ) { for(int j = li1; j >= 1; j--) { d = min(d, dis(p[i1], p[j])); if(((p[i1].x - p[j].x)*(p[i1].x - p[j].x) >= d)|| j == 1) { i1++; li1 = i1-1; break;} if(tot1 >= tot2) { tot1 += 200; li1 = j-1; break; } tot1++; } for(int j = li2; j >= 1; j--) { d = min(d, dis(p2[i2], p2[j])); if(((p2[i2].y - p2[j].y)*(p2[i2].y - p2[j].y) >= d) || j == 1) { i2++; li2 = i2-1; break; } if(tot2 >= tot1) { tot2 += 200; li2 = j-1; break; } tot2++; } } printf("%.2f\n", sqrt(d)/2); } }
时间: 2024-11-08 18:20:32