hdu 1007 /ZOJ 2107 Quoit Design (二分,最近点距离)

题目地址:hdu:点击打开链接

    ZOJ:点击打开链接


该代码在ZOJ能AC,但hdu就不行,不过可以作为一个经典案例分析:

#include<stdio.h>
#include<math.h>
#include <stdlib.h>

/*结构体尽量写成全局变量*/
struct point{
    double x,y;
}node[100005];

int tmp[100005];

double min(double a,double b){
  if(a<=b)
    return a;
  if(a>b)
    return b;
}
/*结构体的快排,注意返回值是int,如果直接两double相减会出错*/
int cmpx( const void *a , const void *b ){
    struct point *c = (struct point *)a;
    struct point *d = (struct point *)b;
    if(c->x != d->x) return c->x < d->x;
    else return d->y < c->y;
}
/*传的数组作为下标时可以引入中间变量,只要控制传回的-1,0,1正确即可*/
int cmp( const void *a ,const void *b){
    double  temp = ((struct point*)a)->y-((struct point*)b)->y;
      if(temp>0)
          return 1;
      else if(temp==0)
          return 0;
      else
          return -1;
}

double dist(struct point a,struct point b){
    double dis=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    return sqrt(dis);
}
double min_dist(int left,int right){
  int i,j;
  double d=1e100;
  /*分的只有一个点时肯定不能算进去,算作无穷大*/
  if(left==right)
    return d;
  /*两个点时传回距离*/
  else if(left+1==right)
    return dist(node[left],node[right]);
  int mid=(left+right)/2;
  d=min(min_dist(left,mid),min_dist(mid+1,right));

  /*搞完上面的才能搞下面的,也就是说多次递归后直到计算完d才进行下面的
  而计算中间矩形区域最小值是不需要递归的*/
  int pos=0;
  /*一个O(n)复杂度的循环真的不算什么,O(n)的循环尽管用就行*/
  for(i=left;i<=right;i++){
    if(fabs(node[i].x-node[mid].x)<=d)   /*把以mid为中线,左右两边距离为d的矩形里的点都搞进来*/
      tmp[pos++]=i;                      /*记录有几个点和其位置*/
  }
  qsort(tmp,pos,sizeof(tmp[0]),cmp);     /*把记录的这几个数按y排了*/
  for(i=0;i<pos;i++)
  for(j=i+1;j<pos&&node[tmp[j]].y-node[tmp[i]].y<=d;j++){  /*把y轴上的距离判断一下,主要是若单看y上的投影都比d大,距离肯定更大了*/
    double dd=dist(node[tmp[i]],node[tmp[j]]);            /*其实每个点只要和对面判断6次就行了。符合条件比较下距离*/
    d=min(d,dd);
  }
  return d;
}

int main(){
  int i,j,n,a,b;
  while(scanf("%d",&n)&&n){
    for(i=0;i<n;i++)
      scanf("%lf%lf",&node[i].x,&node[i].y);
    /*超时的原因可能是快排最坏时间复杂度太高*/
    qsort(node,n,sizeof(node[0]),cmpx);
    double ans=min_dist(0,n-1)/2.0;
    printf("%.2lf\n",ans);

  }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值