2022.3.13
阿新 • • 發佈:2022-03-13
藍書
AcWing 119. 襲擊
思路:平面最近點對,多了個陣營的區別,但還是調了好久,有以下幾點需要注意:1,題目資料範圍太大如果分治的時候直接sort會超時,得用歸併排序。2.因為是浮點數的判斷所以得加eps。3.要特判一下當點的型別相同的時候為了不影響最小值的判斷,讓他們變成當前的最小值就可以。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N = 2e5 + 10; const double INF = 1e10,eps=1e-6; double mmin; struct node { double x, y; int id; } point[N],tmp[N]; bool cmp(node a, node b) { return a.x < b.x; } bool cmp2(node a, node b) { return a.y < b.y; } double dist(node a,node b) { if (a.id == b.id) return mmin; return (double)sqrt((double)(a.x - b.x) * (a.x - b.x) + (double)(a.y - b.y) * (a.y - b.y)); } double solve(int l,int r) { if(l>=r) return INF; int mid = l + r >> 1; double midx = point[mid].x; int midid = point[mid].id; double res = min(solve(l, mid), solve(mid + 1, r)); int k = 0,i=l,j=mid+1; while(i<=mid&&j<=r) { if(point[i].y<point[j].y) tmp[k++] = point[i++]; else tmp[k++]=point[j++]; } while(i<=mid) tmp[k++] = point[i++]; while(j<=r) tmp[k++] = point[j++]; for (int i = l, j = 0; i <=r;i++,j++) point[i] = tmp[j]; k = 0; for (int i = l; i <= r; i++) { // cout << midid << ' ' << point[i].id << '\n'; if (point[i].x >= midx - res && point[i].x <= midx + res) tmp[k++] = point[i]; } for (int i = 0; i < k; i++) { // cout << midid << ' ' << point[i].id << '\n'; for (int j = i + 1; j < k && tmp[i].y - tmp[j].y+eps <= res; j++) { //if (tmp[i].id != tmp[j].id) // cout << dist(tmp[i], tmp[j]) << endl; res = min(res, dist(tmp[i], tmp[j])); } } mmin = min(mmin, res); return res; } int main() { //ios::sync_with_stdio(false); //cin.tie(0); int t; scanf("%d", &t); while(t--) { int n; scanf("%d", &n); for (int i = 0; i < n;i++) { scanf("%lf%lf", &point[i].x, &point[i].y); point[i].id = 1; } for (int i = n; i < n*2;i++) { scanf("%lf%lf", &point[i].x, &point[i].y); point[i].id = 2; } sort(point, point + 2 * n, cmp); mmin = dist(point[0], point[2 * n - 1]); printf("%.3lf\n",solve(0, 2 * n-1)); } return 0; }