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

洛谷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;
} 

原文地址:https://www.cnblogs.com/twilight-sx/p/8455706.html

时间: 2024-11-13 08:07:51

【题解】平面最近点对(加强版)的相关文章

「LuoguP1429」 平面最近点对(加强版)

题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开. 输出格式: 仅一行,一个实数,表示最短距离,精确到小数点后面4位. 输入输出样例 输入样例#1: 复制 3 1 1 1 2 2 2 输出样例#1: 复制 1.0000 说明 0<=x,y<=10^9 题解 考场清晰的记得以前听过,并且记错做法还觉得

Luogu P1429 平面最近点对(加强版)

P1429 平面最近点对(加强版) 题意 题目描述 给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的. 输入输出格式 输入格式: 第一行:\(n\):\(2\leq n\leq 200000\) 接下来\(n\)行:每行两个实数:\(x\ y\),表示一个点的行坐标和列坐标,中间用一个空格隔开. 输出格式: 仅一行,一个实数,表示最短距离,精确到小数点后面\(4\)位. 输入输出样例 输入样例#1: 3 1 1 1 2 2 2 输出样

P1429 平面最近点对(加强版)(分治)

P1429 平面最近点对(加强版) 主要思路: 分治,将点按横坐标为第1关键字升序排列,纵坐标为第2关键字升序排列,进入左半边和右半边进行分治. 设d为左右半边的最小点对值.然后以mid这个点为中心,扩展宽为2d,长为2d的正方形.除了这个正方形外的点都不可能使答案更小.而且这个正方形里至多8个点(可以证明至多6个,我不会.but,知道至多8个就够了,这样已经保证了复杂度.)一句话证明:如果多余8个点,那么必有2个点的最小距离比d小.这8个点内暴力枚举就好了. //luoguP1429 #inc

HDU 5721 Palace BestCoder 2nd Anniversary (平面最近点对)

Palace Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 465    Accepted Submission(s): 118 Problem Description The last trial Venus imposes on Psyche is a quest to the underworld. She is to ta

hdu1007 平面最近点对(暴力+双线程优化)

突发奇想,用双线程似乎可以优化一些暴力 比如说平面最近点对这个题目,把点复制成2份 一份按照x排序,一份按照y排序 然后双线程暴力处理,一份处理x,一份处理y 如果数据利用x递减来卡,那么由于双线程,它卡不住y 如果数据利用y递减来卡,那么卡不住x 这样暴力n^2就可以过了 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algori

平面最近点对(分治nlogn)

平面最近点对,是指给出平面上的n个点,寻找点对间的最小距离 首先可以对按照x为第一关键字排序,然后每次按照x进行分治,左边求出一个最短距离d1,右边也求出一个最短距离d2,那么取d=min(d1, d2) 然后只需考虑横跨左右两侧的点,不妨枚举左侧的点pi 那么很显然的是如果pi距离中间的点超过了d,便可以直接舍去,只需考虑距离中间点小于d的点 这样一来就可以对每个pi画一个边长为2d的正方形,易证,矩形内最多存在8个点. 那么关键问题就是要快速找这8个点 朴素做法是对分治后的点进行快排,这样复

POJ 3714 Raid(平面最近点对)

解题思路: 分治法求平面最近点对,点分成两部分,加个标记就好了. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <iomanip>

平面最近点对

HDU 1007 求平面最近点对距离的一半 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const double eps = 1e-7; const int MAXN = 100010; const double INF = 1e20; struct Point

分治法二(平面最近点对)

上篇文章介绍了分治法的概念和基本解题步骤,并附加了一个例题帮助大家了解分治法的基本思想,在这篇文章中,我将对分治法的另一个经典问题进行分析,希望我的文章能够将今天的主题解释清楚.接下来我将用三种不同的方法求解"平面最近点对"问题. 问题描述:在一个平面上随机分布着 n 个点,现给定 n 个点的坐标,要求给出最近的两个点之间的距离. 方法一:原始方法 题目要求求出最近的两点之间的距离,先整理一下已知的线索:首先点的总个数为 n :其次已知 n 个点的坐标.掌握了每个点的坐标,就相当于间接

HDU1007--Quoit Design(平面最近点对)

Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some toys, with all the toys encircled awarded.In the field of Cyberground, the position of each toy is fixed, and the ring is carefull