求最近点对(分治算法的运用)

原题:http://acm.hdu.edu.cn/showproblem.php?pid=1007

条件:

         多组测试数据,n个点(2<=n<=100000),接下来输入n行点对,求点对之间距离的最小值的一半,保留两位小数。

解题思路:

        以x坐标和y坐标分别进行归并排序,当x值相等时,以y值小的在前,当y值相等也是相似。

解题代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#define MAX 2147483647
using namespace std;
double c[100005][2];
void MergeSort(double a[][2],int left,int middle,int right,double c[][2])
{
    int x=left,x1=middle+1;
    int y=middle,y1=right,k=0;
    while(x<=y&&x1<=y1)
    {
        if(a[x][0]<a[x1][0])
        {
            c[k][0]=a[x][0];
            c[k++][1]=a[x++][1];
        }
        else if(a[x][0]==a[x1][0])
        {
            if(a[x][1]<=a[x1][1])
            {
                c[k][0]=a[x][0];
                c[k++][1]=a[x++][1];
            }
            else
            {
                c[k][0]=a[x1][0];
                c[k++][1]=a[x1++][1];
            }
        }
        else
        {
            c[k][0]=a[x1][0];
            c[k++][1]=a[x1++][1];
        }
    }
    while(x<=y)
    {
        c[k][0]=a[x][0];
        c[k++][1]=a[x++][1];
    }
    while(x1<=y1)
    {
        c[k][0]=a[x1][0];
        c[k++][1]=a[x1++][1];
    }
    for(int i=0;i<k;i++)
    {
        a[left+i][0]=c[i][0];
        a[left+i][1]=c[i][1];
    }
}
void SplitArray(double a[][2],int left,int right,double c[][2])
{
    if(left<right)
    {
        int middle=(left+right)/2;
        SplitArray(a,left,middle,c);
        SplitArray(a,middle+1,right,c);
        MergeSort(a,left,middle,right,c);
    }
}
void MergeSort1(double a[][2],int left,int middle,int right,double c[][2])
{
    int x=left,x1=middle+1;
    int y=middle,y1=right,k=0;
    while(x<=y&&x1<=y1)
    {
        if(a[x][1]<a[x1][1])
        {
            c[k][0]=a[x][0];
            c[k++][1]=a[x++][1];
        }
        else if(a[x][1]==a[x1][1])
        {
            if(a[x][0]<=a[x1][0])
            {
                c[k][0]=a[x][0];
                c[k++][1]=a[x++][1];
            }
            else
            {
                c[k][0]=a[x1][0];
                c[k++][1]=a[x1++][1];
            }
        }
        else
        {
            c[k][0]=a[x1][0];
            c[k++][1]=a[x1++][1];
        }
    }
    while(x<=y)
    {
        c[k][0]=a[x][0];
        c[k++][1]=a[x++][1];
    }
    while(x1<=y1)
    {
        c[k][0]=a[x1][0];
        c[k++][1]=a[x1++][1];
    }
    for(int i=0;i<k;i++)
    {
        a[left+i][0]=c[i][0];
        a[left+i][1]=c[i][1];
    }
}
void SplitArray1(double a[][2],int left,int right,double c[][2])
{
    if(left<right)
    {
        int middle=(left+right)/2;
        SplitArray1(a,left,middle,c);
        SplitArray1(a,middle+1,right,c);
        MergeSort1(a,left,middle,right,c);
    }
}
int main()
{
    int n,x,y;
    double a[100005][2],min1=MAX,min2=MAX;
    while(scanf("%d",&n)!=EOF&&n!=0)
    {
        min1=MAX;
        min2=MAX;
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&a[i][0],&a[i][1]);
        SplitArray(a,0,n-1,c);
        for(int i=0;i<n-1;i++)
        {
            int j=i+1;
            while(true&&j!=n)
            {
                min1=min(min1,pow(abs(a[i][0]-a[j][0]),2)+pow(abs(a[i][1]-a[j][1]),2));
                if(a[j][0]!=a[j+1][0]||a[i][0]==a[j][0])
                    break;
                else
                    j++;
            }
        }
        SplitArray1(a,0,n-1,c);
        for(int i=0;i<n-1;i++)
        {
            int j=i+1;
            while(true&&j!=n)
            {
                double ans=pow(abs(a[i][0]-a[j][0]),2)+pow(abs(a[i][1]-a[j][1]),2);
                min2=min(min2,ans);
                if(a[j][1]!=a[j+1][1]||a[i][1]==a[j][1])
                    break;
                else
                    j++;
            }
        }
        min1=min(min1,min2);
        min1=sqrt(min1)/2;
        printf("%.2lf\n",min1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值