POJ 3714 Raid(平面最近点对)

解题思路:

分治法求平面最近点对,点分成两部分,加个标记就好了。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <string.h>
#define LL long long
using namespace std;
const int MAXN = 200000 + 10;
const double INF = 1e100;
struct Point
{
    double x, y;
    int flag;
}P[MAXN];
int N;
Point vec[MAXN];
bool cmp_x(Point a, Point b)
{
    return a.x < b.x;
}
bool cmp_y(Point a, Point b)
{
    return a.y < b.y;
}
double dis(Point a, Point b)
{
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}
double solve(Point *a, int l, int r)
{
    if(l == r) return INF;
    if(l + 1 == r)
    {
        if(P[l].flag == P[r].flag)
            return INF;
        return dis(P[l], P[r]);
    }
    int m = (l + r) >> 1;
    double d = solve(a, l, m);
    d = min(d, solve(a, m + 1, r));
    int sz = 0;
    for(int i=l;i<=r;i++)
    {
        if(fabs(P[i].x - P[m].x) <= d)
            vec[sz++] = P[i];
    }
    sort(vec, vec + sz, cmp_y);
    for(int i=0;i<sz;i++)
    {
        for(int j=i+1;j<sz;j++)
        {
            if(fabs(vec[i].y - vec[j].y) >= d)
                break;
            if(vec[i].flag != vec[j].flag)
            {
                double rs = dis(vec[i], vec[j]);
                if(rs < d) d = rs;
            }
        }
    }
    return d;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &N);
        for(int i=0;i<N;i++)
        {
            scanf("%lf%lf", &P[i].x, &P[i].y);
            P[i].flag = 0;
        }
        for(int i=0;i<N;i++)
        {
            scanf("%lf%lf", &P[i + N].x, &P[i + N].y);
            P[i + N]. flag = 1;
        }
        N <<= 1;
        sort(P, P + N, cmp_x);
        double ans = solve(P, 0, N - 1);
        printf("%.3f\n", ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-31 14:25:31

POJ 3714 Raid(平面最近点对)的相关文章

POJ 3714 Raid 平面最近点对

题目大意:给出两个集合的点,问这两个集合之间最近的点对的距离是多少. 思路:先要知道平面最近点对的分治算法,剩下的就简单了,只需要在更新答案的时候判断一下两个点是否属于两个集合就可以了. 分治算法总是十分神奇的. 对于平面最近点对,首先按照x坐标排序,然后递归进行分治,每次分治时,先获得分治得到的结果,然后按照这个结果来计算本区间.由于我们只需要计算答案小于这个结果的点对就行了,其中(l,mid)和(mid + 1,r)我们已经得到答案,只需要统计一个点在(l,mid),另一个点在(mid +

POJ 3714 Raid 最近对点题解

本题是一般最近对点求解,稍微增加点限定:有两个集合点,要求不同集合中的点的最近对. 那么就增加一个判断,如果是同一个集合中的点,那么就返回最大值,其他和一般的最近对点解法一样. 注意:本题数据有重合点,那么就要防止分类的时候溢出. Geeks上的最近对的程序是无法处理有重合点的情况的. #include <stdio.h> #include <stdlib.h> #include <float.h> #include <math.h> #include &l

poj 3714 Raid 分治法求平面最近点对

题意: 给平面上的n个点,求两点间的最短距离. 分析: 分治法,保存点用vector会tle... 代码: //poj 3714 //sep9 #include <iostream> #include <algorithm> #include <cmath> using namespace std; const double INF=1e50; struct P { double x,y; int type; }p[240000],b[240000]; bool cmp

【POJ 3714】 Raid

[题目链接] http://poj.org/problem?id=3714 [算法] 分治求平面最近点对 [代码] #include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #

poj 3714 最近点对

题意: 给出n个a类点,n个b类点,求a类点到b类点的最近距离. 限制: 1 <= n <= 1e5 0 <= x,y <= 1e9 思路: 点分治 /*poj 3714 题意: 给出n个a类点,n个b类点,求a类点到b类点的最近距离. 限制: 1 <= n <= 1e5 0 <= x,y <= 1e9 思路: 点分治 */ #include<iostream> #include<cstdio> #include<algorit

$Poj3714/AcWing\ Raid$ 分治/平面最近点对

$AcWing$ $Sol$ 平面最近点对板子题,注意要求的是两种不同的点之间的距离. $Code$ #include<bits/stdc++.h> #define il inline #define Rg register #define go(i,a,b) for(Rg int i=a;i<=b;++i) #define yes(i,a,b) for(Rg int i=a;i>=b;--i) #define mem(a,b) memset(a,b,sizeof(a)) #def

poj3714 Raid(分治求平面最近点对)

题目链接:https://vjudge.net/problem/POJ-3714 题意:给定两个点集,求最短距离. 思路:在平面最近点对基础上加了个条件,我么不访用f做标记,集合1的f为1,集合2的f为-1,那么求两个点的距离时,如果a.f*b.f=-1时计算距离,否则乘积为1的话返回inf.其它就和hdoj1007一样了. AC代码: #include<cstdio> #include<algorithm> #include<cmath> #include<cs

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个点 朴素做法是对分治后的点进行快排,这样复