zoukankan      html  css  js  c++  java
  • HDU 1007(套圈 最近点对距离)

    题意是求出所给各点中最近点对的距离的一半(背景忽略)。

    用分治的思想,先根据各点的横坐标进行排序,以中间的点为界,分别求出左边点集的最小距离和右边点集的最小距离,然后开始合并,分别求左右点集中各点与中间点的距离,从这些距离与点集中的最小距离比较,求得最小距离,此处可按纵坐标排序,将纵坐标距离已经大于之前最小距离的部分都剪枝。

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n,a[100009];
     4 struct point
     5 {
     6     double x,y;
     7 }p[100009];
     8 bool cmpx(point a,point b)
     9 {
    10     return a.x < b.x;
    11 }
    12 bool cmpy(int a,int b)
    13 {
    14     return p[a].y < p[b].y;
    15 }
    16 double dis(point a,point b)
    17 {
    18     return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
    19 }
    20 double min(double a,double b,double c)
    21 {
    22     if(a>b) return b>c?c:b;
    23     return a>c?c:a;
    24 }
    25 double fin(int from,int to)
    26 {
    27     if(from+1 == to ) return dis(p[from],p[to]);
    28     if(from+2 == to ) return min(dis(p[from],p[from+1]),dis(p[from],p[to]),dis(p[from+1],p[to]));
    29     int mid = (from+to)>>1;
    30     double ans = min(fin(from,mid),fin(mid+1,to));
    31     int cnt = 0;
    32     for(int i = from; i <= to; i++)
    33         if(abs(p[i].x-p[mid].x) <= ans) a[cnt++] = i;
    34     sort(a,a+cnt,cmpy);
    35     for(int i = 0; i < cnt; i++)
    36         for(int j = i+1; j < cnt; j++)
    37         {
    38             if(p[a[j]].y-p[a[i]].y >= ans) break;
    39             ans = min(ans,dis(p[a[i]],p[a[j]]));
    40         }
    41     return ans;
    42 }
    43 int main()
    44 {
    45     while(scanf("%d",&n)&&n)
    46     {
    47         for(int i = 0; i < n; i++)
    48             scanf("%lf %lf",&p[i].x,&p[i].y);
    49         sort(p,p+n,cmpx);
    50         printf("%.2lf
    ",fin(0,n-1)/2);
    51     }
    52     return 0;
    53 }
    View Code

    但是呢,开始时本人并不是这么写的,而是求了所有点中最小的横坐标和纵坐标,然后以此为参照点,分别求其他各点到参照点的距离,以距离排序,再求出相邻两点距离的最小值。这么写是上面写法的用时一半左右,尽管 AC 了,但是这么写是不对的......

    如图所示,图中的点 1 和点 2 距离比点 1 和点 3 的距离更近,但是第二种方法则是用点 1 和点 3距离与点 3 和点 2 距离中求较小值。(题目的测试数据中可能没有这样的数据吧......)

    第二种方法的代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 struct point
     5 {
     6     double x,y,dis;
     7 }st,p[100009];
     8 bool cmp(point a,point b)
     9 {
    10     if(a.dis!=b.dis) return a.dis < b.dis;
    11     return a.x<b.x;
    12 }
    13 double dist(point a,point b)
    14 {
    15     return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
    16 }
    17 int main()
    18 {
    19     double sml;
    20     while(scanf("%d",&n)&&n)
    21     {
    22         st.x = st.y = 1000000.0;
    23         sml = 1000000.0;
    24         for(int i = 0; i < n; i++)
    25         {
    26             scanf("%lf %lf",&p[i].x,&p[i].y);
    27             if(p[i].x < st.x) st.x = p[i].x;
    28             if(p[i].y < st.y) st.y = p[i].y;
    29         }
    30         for(int i = 0; i < n; i++)
    31             p[i].dis = dist(p[i],st);
    32         sort(p,p+n,cmp);
    33         for(int i = 1; i < n; i++)
    34             if(dist(p[i],p[i-1])<sml) sml = dist(p[i],p[i-1]);
    35         printf("%.2lf
    ",sml/2);
    36     }
    37     return 0;
    38 }
    View Code
    日后若能有更好的想法,再来完善。 希望看到的大神不吝赐教 orz
  • 相关阅读:
    空间换时间之反范式设计之路/合理冗余/去除外键
    WebAPI接口设计:SwaggerUI文档 / 统一响应格式 / 统一异常处理 / 统一权限验证
    开放api接口签名验证
    EasyUI开发踩过的坑(EasyUI开发笔记)
    nuget挂了吗?
    C# 实体/集合差异比较,比较两个实体或集合值是否一样,将实体2的值动态赋值给实体1(名称一样的属性进行赋值)
    从应用的角度讲创业公司该如何选择域名?
    疑似easyui本身bug:easyui时间控件问题,试了几个版本都不行
    工作三年对程序的理解特来求证
    控制器读取视图表单中的数据的几种方式
  • 原文地址:https://www.cnblogs.com/Taskr212/p/9513210.html
Copyright © 2011-2022 走看看