1. 程式人生 > 其它 >2022.3.13

2022.3.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;
}