`
Coco_young
  • 浏览: 125789 次
  • 性别: Icon_minigender_1
  • 来自: 湖南长沙
社区版块
存档分类
最新评论

[最近点对]HDOJ 1007 Quoit Design

 
阅读更多

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

题目大意:在平面上有N个点,求出两点之间距离的最小值/2,就是结果.

算法详细介绍:http://blog.csdn.net/guyulongcs/article/details/6841550,这里讲得很清楚。

也就是一个很裸的算法题吧,要求用O(nlogn)的算法求出最近点对,翻了翻算法导论,看完了上面用分治法解答,自己实现的时候有几个点需要注意:

1.如果每次递归求解的时候,开出新的数组来保存,集合Sy的划分,那么一定会MLE,看了别人的代码后,发现可以用先分解,再归并,那么只需要增加一个辅助数组,解决了MLE的问题。

2.关于如何分解原问题,开始用的是算法导论上说的,以Sx的中间点的横坐标来划分,分解成<=Sx[mid].x的和>=Sx[mid].x的,这样只用一个辅助数组的方法不适用,因为可能有很多点的横坐标相同,再想到分解成<=Sx[mid].x的和>Sx[mid].x的,这样也行不通,因为可能导致>Sx[mid].x的部分没有点,在某算法模板上看到,可以按照元素在最开始的Sx中的顺序,为每个元素增加一个域index来记录该元素在Sx中处于什么位置,这样就可以把问题分解成<=Sx[mid].index的和>Sx[mid].index的,没有问题。

3.总结最近点对的整体算法框架:

(1)预处理,用两个集合Sx,Sy保存所有的点,不同的是Sx按照x升序排列,Sy按照y升序排列。

(2)递归求解:边界条件为,当前待处理点集的点的个数<=3

递归框架为,分解Sx,分解Sy,并保证Sy的两个子集按y的升序排列,递归求解,用归并将Sy还原到没分解以前,合并子问题。

4.关于合并子问题的正确性证明还有待研究。

AC代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN = 100010;
const double inf = 10e100;
#define SQL(x) (x)*(x)
struct Point
{
  double x,y;
  int index;     
}sx[MAXN],sy[MAXN],st[MAXN];
bool x_cmp(const Point &p1,const Point &p2)
{
     return p1.x<p2.x;
}
bool y_cmp(const Point &p1,const Point &p2)
{
     return p1.y<p2.y;
}
double dis(Point p1,Point p2)
{
       return sqrt(SQL(p1.x-p2.x)+SQL(p1.y-p2.y));
}
double merge(Point sy[],Point st[],int l,int r,double dist,double L)
{
       int Len = 0;
       for(int i=l;i<=r;i++)
       {
           if(sy[i].x>(L-dist)&&sy[i].x<(L+dist))st[Len++]=sy[i];
       }
       
       for(int i=0;i<Len;i++)
       {
           for(int j=i+1;j<Len&&j<i+8;j++)
           {
               dist = min(dist,dis(st[i],st[j]));
           }
       }
       return dist;
}
double solve(Point sx[],Point sy[],Point st[],int l,int r)
{
       if(r==l)return inf;
       else if(r-l==1)return dis(sx[l],sx[r]);
       else if(r-l==2)
       {
            double x1 = dis(sx[l],sx[l+1]);
            double x2 = dis(sx[l],sx[r]);
            double x3 = dis(sx[l+1],sx[r]);
            x1 = min(x1,x2);
            x1 = min(x1,x3);
            return x1;
       }
       else
       {
           int m = (l+r)>>1,i,j,k;
           double L = sx[m].x, dist;
           for(i=l,j=l,k=m+1;i<=r;)
           {
               if(sy[i].index<=sx[m].index)st[j++]=sy[i++];
               else st[k++]=sy[i++];
           }
           //printf("%d %d ~~~\n",j,k);
           for(i=l;i<=r;i++)sy[i]=st[i];//,printf("%.2lf %.2lf\n",st[i].x,st[i].y);system("pause");
           double p = solve(sx,sy,st,l,m),q = solve(sx,sy,st,m+1,r);
           //printf("%.2lf  %.2lf\n",p,q);system("pause");
           dist = min(p,q);
           for(i=l,j=l,k=m+1;j<=m&&k<=r;)
           {
               if(sy[j].y<sy[k].y)st[i++]=sy[j++];
               else if(sy[j].y>sy[k].y)st[i++]=sy[k++];
               else
               {
                   if(sy[j].index<sy[k].index)st[i++]=sy[j++];
                   else st[i++] = sy[k++];
               }
           }
           while(j<=m)st[i++]=sy[j++];
           while(k<=r)st[i++]=sy[k++];
           for(i=l;i<=r;i++)sy[i]=st[i];
           //system("pause");
           dist = merge(sy,st,l,r,dist,L); 
           //printf("%.2lf\n",dist);
           return dist;
       }
}
int main()
{
    int n;
    //freopen("in.txt","r",stdin);
    //freopen("out2.txt","w",stdout);
    while(scanf("%d",&n),n)
    {
        for(int i=0;i<n;i++)
        scanf("%lf%lf",&sx[i].x,&sx[i].y);
        stable_sort(sx,sx+n,x_cmp);
        for(int i=0;i<n;i++)
        sx[i].index = i,sy[i]=sx[i];
        stable_sort(sy,sy+n,y_cmp);
        //for(int i=0;i<n;i++)printf("%.2lf %.2lf %d\n",sx[i].x,sx[i].y,sx[i].index);
        //printf("\n");
        //for(int i=0;i<n;i++)printf("%.2lf %.2lf %d\n",sy[i].x,sy[i].y,sy[i].index);
        printf("%.2lf\n",solve(sx,sy,st,0,n-1)/2);
    }
}


分享到:
评论

相关推荐

    分治法求最近点对

    **标题解析:**“分治法求最近点对”指的是使用分治策略来解决寻找二维空间中距离最近的两个点的问题。在计算机科学中,分治法是一种将复杂问题分解成更小、易于处理的部分的方法,然后分别解决这些部分,最后合并...

    HDOJ题目分类 HDOJ题目分类

    【标题】:“HDOJ题目分类 HDOJ题目分类” HDOJ,全称为Happy DingO Online Judge,是一个在线编程竞赛平台,它为参赛者提供了大量编程题目进行练习和比赛,旨在提升编程技能和算法理解。HDOJ的题目分类是帮助用户...

    hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000

    【标题】"hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000" 涉及的知识点主要围绕着“杭电在线判题系统(HDOJ)”以及其中的题目1082和10系列题目。HDOJ是杭州电子科技大学主办的一个在线编程竞赛平台,...

    hdoj--acm题目,有注释

    下面是对每个题目的知识点总结: 2000:本题目要求输入三个字符,输出按照从小到大排序的结果。本代码使用了 While 循环和 scanf 函数来读取输入,使用了 temp 变量来实现数据交换。这种方法可以避免使用数组和复杂...

    HDOJ1002

    ACM ICPC HDOJ1002

    HDOJ1001

    ACM ICPC HDOJ1001

    hdoj1001标程

    hdoj1001标程

    HDOJ 80题 Java

    【标题】"HDOJ 80题 Java"是一份专为Java程序员设计的在线编程挑战集合,源自杭州电子科技大学(HDOJ)的在线评测系统。这些题目旨在帮助Java开发者提升算法理解与编程能力,同时也为那些习惯于C++但希望在Java环境...

    HDOJ部分简单题(JAVA)

    HDOJ1000.java HDOJ1001.java HDOJ1089.java HDOJ1090.java HDOJ1091.java HDOJ1092.java HDOJ1093.java HDOJ1094.java HDOJ1095.java HDOJ1108.java HDOJ1406.java HDOJ2001.java HDOJ2002.java HDOJ2003.java HDOJ...

    hdoj1004 解题代码 答案

    hdoj1004,解题代码,答案代码,欢迎下载

    ACM HDOJ 课件

    在处理图形和空间问题时,计算几何提供了有效的算法,如最近点对查找、凸包计算等。 通过学习这些课件,参赛者可以系统地提升自己的算法水平,更好地应对ACM竞赛和HDOJ题目的挑战。此外,这些知识同样适用于实际的...

    HDOJ离线版

    《HDOJ离线版:探索编程竞赛的智慧宝库》 HDOJ,全称为“杭州电子科技大学在线评测系统”(Hangzhou Dianzi University Online Judge...所以,如果你对编程有热情,对挑战自我有兴趣,那么HDOJ离线版绝对值得你拥有。

    hdoj2066最短路

    根据给定的文件信息,我们可以总结出以下关于“hdoj2066最短路径”的相关知识点: ## hdoj2066最短路径概述 ### 标题解析:“hdoj2066最短路” - **hdoj**:High Density Online Judge(高密度在线评测系统),是...

    HDOJ1003

    ACM ICPC HDOJ1003

    HDOJ 1008

    ACM ICPC HDOJ1008

    hdoj1002——大整数相加

    ### hdoj1002——大整数相加 #### 题目背景与目的 本题目来源于杭州电子科技大学的在线评测系统(HDOJ),编号为1002的大整数相加问题。该题目主要考察的是编程者对于大整数处理的基本技巧以及对数组、循环等基础...

    hdoj 2013 多校训练4标程+解题报告

    "4标程"意味着包含了四道题目(或者可能是四个阶段)的标准解决方案,而“解题报告”则指的是对这些题目解法的详细分析和总结。 【描述解析】:描述中的“hdoj 2013 多校训练3标程+解题报告”稍有不同,提到了“3标...

    HDOJ1000

    ACM ICPC HDOJ1000

    OJ.tar.gz_HDOJ _OJ源码_oj

    【OJ.tar.gz_HDOJ _OJ源码_oj】是一个包含编程竞赛平台HDOJ(Happy Ding Octopus Judge)部分源代码的压缩文件。这个压缩包的主要目的是供学习和研究使用,尤其是针对50至60题目的解题算法和系统实现。通过分析这些...

    HDOJ.rar_HD_HDOJ

    【标题】"HDOJ.rar_HD_HDOJ" 是一个与HDU(杭州电子科技大学)在线判题系统HDOJ相关的压缩包文件,其中包含了大量编程题目的源代码。 【描述】提到,这个压缩包包含了几百道HDOJ题目的源代码,这意味着它是一个宝贵...

Global site tag (gtag.js) - Google Analytics