hdu 1007(计算几何)

来源:互联网 发布:手机雨滴软件苹果 编辑:程序博客网 时间:2024/04/28 02:52

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1007

题意:在平面上给你很多点,任意两点之间的最短距离。

分析:

一眼看到这个题想到暴力,二重循环,然后一看数据范围果断放弃,然后在网上查了一下就有一个方法可以在nlog(n)的方法求出,分治的思想,我现在听过分治就只在分治排序的那里听过。这个算法的原理是我们先对点进行按x大小进行排序,然后找出x的中位数(mid)在中位数的两边大概会有n/2个点,这个最近的点的距离(两个点)只会在mid左边,或者在mid的右边,最麻烦的可能是一个点在mid的左边另一个在mid的右边。这个算法的难点也在此,mid左边会得到一个最小值 ans1,右边最小值ans2,ans=min(ans1,ans2),如果在mid的两边的点会产生最小距离,则可能产生这些点x是会有一个范围的,mid左右两边扩展ans,得到如下图(别人的 嘿嘿)

然后在通过一个证明,证明太麻烦跳过了,可以得到要满足mid左边的一个和mid右边得一个点构成得距离小于ans,则一个左边的点最多对应右边6个点(可能说的不清楚,但是要说清楚很麻烦,很烦)要想彻底搞懂这个题可以去看看别人得博客 我很菜。

代码:模板吧

#include <iostream>#include <algorithm>#include <math.h>using namespace std;struct node {    double x;    double y;}p[100050];int a[100050];bool cmpx(node qq,node ww){    return qq.x<ww.x; //小到大}bool cmpy(int qq,int ww){    return p[qq].y<p[ww].y; //小到大}double dis(node qq,node zz){    return sqrt(((qq.x-zz.x)*(qq.x-zz.x))+((qq.y-zz.y)*(qq.y-zz.y)));}double find1(int l,int r){    if(l+1==r) return dis(p[l],p[r]);    if(l+2==r) return min(min(dis(p[l],p[l+1]),dis(p[l+1],p[r])),dis(p[l],p[r]));    int mid=(l+r)/2;    double ans;    ans=min(find1(l,mid),find1(mid+1,r));    int cnt=0;    for (int i=l;i<=r;i++)        if(p[i].x>=p[mid].x-ans&&p[i].x<=p[mid].x+ans)            a[cnt++]=i;    sort(a,a+cnt,cmpy);    for (int i=0;i<cnt;i++)    {        for (int j=i+1;j<cnt&&j<i+7;j++)        {            ans=min(ans,dis(p[a[i]],p[a[j]]));        }    }    return ans;}int main (){    int n;    while (scanf ("%d",&n)&&n)    {    for (int i=0;i<n;i++)        scanf ("%lf %lf",&p[i].x,&p[i].y);    sort(p,p+n,cmpx);    //for (int i=0;i<n;i++)      //  printf ("%lf %lf\n",p[i].x,p[i].y);    printf ("%.2lf\n",find1(0,n-1)/2.0);    }    return 0;}
0 0