• 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\n",ans);
        }
    }
  • 相关阅读:
    docker命令总结
    VulToEs
    MYSQL
    MoonStack
    Spring mvc json null
    MySQL
    极光推送
    坑爹的RockSaw和坑爹的windows7
    App接口设计思路
    CSUOJ 1329 一行盒子(数组模拟链表)
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/9315212.html
Copyright © 2020-2023  润新知