POJ 3714 分治/求平面最近点对

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3714 分治/求平面最近点对相关的知识,希望对你有一定的参考价值。

第一次见这种问题直接懵圈。。。没想到分治法这么强大,借鉴了lyd的代码:

代码如下

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn=200010;
struct point{
    int x,y,z;
};
point a[maxn],b[maxn];
int n,m,t,i;
double ans=0;
bool cmp(point a1,point a2){
    return a1.x<a2.x;
}
double dist(point a1,point a2){
    return sqrt(1.0*(a1.x-a2.x)*(a1.x-a2.x)+1.0*(a1.y-a2.y)*(a1.y-a2.y));
}
void merge(int l,int mid,int r){//按照y坐标排序,分治法 
    int i=l,j=mid+1,k;
    for(k=l;k<=r;k++){//两个部分已经按y坐标排好序,直接合并 
        if(j>r||i<=mid&&a[i].y<a[j].y)b[k]=a[i++];
        else b[k]=a[j++];
    }
    for(k=l;k<=r;k++)a[k]=b[k];
}
void solve(int l,int r){
    if(l==r)return;//分治边界
    int mid=(l+r)>>1,p=0,x=a[mid].x,i,j;
    solve(l,mid);//解决左半部分 
    solve(mid+1,r);//右半部分 
    merge(l,mid,r);//合并 
    for(i=l;i<=r;i++){//排除不肯能选项 
        if(abs(a[i].x-x)<=ans)b[++p]=a[i];
    }
    for(i=1;i<p;i++)
        for(j=i+1;j<=p;j++){
            if(b[j].y-b[i].y<ans){//y坐标之差小于ans才有可能是 
                if(b[i].z!=b[j].z)//如果不在一个集合 
                    ans=min(ans,dist(b[i],b[j]));
            }
            else//若这个不行,后面的肯定也不行 
                break;
        }
}
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].z=1;
        for(i=n+1,n*=2;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].z=2;
        ans=dist(a[1],a[n]);
        sort(a+1,a+1+n,cmp);//根据x坐标排序 
        solve(1,n);
        printf("%.3f
",ans);
    }
}

 

以上是关于POJ 3714 分治/求平面最近点对的主要内容,如果未能解决你的问题,请参考以下文章

poj 3714 Raid(平面最近点对)

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

POJ3714:求平面最近点对

POJ 3714 Raid

poj3714 Raid

平面最近点对-分治