码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-07-15 23:27:40      阅读:375      评论:0      收藏:0      [点我收藏+]

标签:坐标   max   根据   ring   2.x   poj   while   ble   ||   

第一次见这种问题直接懵圈。。。没想到分治法这么强大,借鉴了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\n",ans);
    }
}

 

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

标签:坐标   max   根据   ring   2.x   poj   while   ble   ||   

原文地址:https://www.cnblogs.com/pkgunboat/p/9315212.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!