• 【题解】平面最近点对(加强版)


    洛谷P1429 很久以前就见过并想做的一道题……

    但大概是那个时候太蒻竟然一直不敢做呢,想想时间真的过得好快,从写‘Hello World’到如今,其实也不过是短短的一个学期呀。

    这道题主要用分治的思想来做,对所有的点排一下序,然后每一次分成两队来处理。若一队的节点数<=3那么就直接暴力求解。可以注意到因为点都是排好序的,所以两边当中的点的距离>= abs(P[i].x - P[mid].x)。那么如果这个距离已经大于我们当前找到的最优答案,显然就不需要再去计算一遍啦。那么我们再把那些还可能含有最优答案的点拿出来暴力处理,因为有前面一个条件的限制,所以实际上这些点的数量是十分有限的。

    虽然是道简单的题目,但从不敢做到今天能够自己写出代码来,还是很受鼓励的吧。

    #include <bits/stdc++.h>
    using namespace std;
    #define INF 999999999.00
    #define maxn 2005000
    int n;
    struct node
    {
        double x, y;
    }P[maxn];
    node q1[maxn], q2[maxn];
    
    bool cmp(node a, node b)
    {
        return a.x < b.x;
    }
    
    double Dis(double x1, double y1, double x2, double y2)
    {
        return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }
    
    double Get_ans(int cnt, int cnt2)
    {
        double ans = INF;
        for(int i = 1; i <= cnt; i ++)
            for(int j = 1; j <= cnt2; j ++)
                ans = min(ans, Dis(q1[i].x, q1[i].y, q2[j].x, q2[j].y));
        return ans;
    }
    
    double Violence(int l, int r)
    {
        double ans = INF;
        for(int i = l; i <= r; i ++)
            for(int j = i + 1; j <= r; j ++)
                ans = min(ans, Dis(P[i].x, P[i].y, P[j].x, P[j].y));
        return ans;
    }
    
    double Div(int l, int r)
    {
        int cnt = 0, cnt2 = 0;
        double ans, ans1, ans2;
        int mid = (l + r) >> 1; 
        if(r - l > 3) ans1 = Div(l, mid), ans2 = Div(mid + 1, r);
        else return Violence(l, r);
        ans = min(ans1, ans2);
        for(int i = mid + 1; i <= r; i ++)
            if(P[i].x - P[mid].x < ans) q1[++ cnt] = P[i];
            else break;
        for(int i = mid; i >= l; i --)
            if(P[mid].x - P[i].x < ans) q2[++ cnt2] = P[i];
            else break;
        return min(ans, Get_ans(cnt, cnt2));
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++)
            scanf("%lf%lf", &P[i].x, &P[i].y);
        sort(P + 1, P + 1 + n, cmp);
        printf("%.4lf", Div(1, n));
        return 0;
    } 
  • 相关阅读:
    C#随笔
    C# 程序间通信的各种途径及解析
    C#控件根据窗体改变大小
    c# SqlHelper Class
    初始Java
    函数基础
    基本数据类型的高级特性:
    python基础
    C#double转化成字符串 保留小数位数, 不以科学计数法的形式出现。
    Oracle使用dblink导入数据
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8455706.html
Copyright © 2020-2023  润新知