您的位置:首页 > 其它

HDU 1007 Quoit Design(计算几何 平面最近点对)

2013-07-19 11:12 585 查看


Quoit Design

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 22349    Accepted Submission(s): 5735


Problem Description

Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some toys, with all the toys encircled awarded.

In the field of Cyberground, the position of each toy is fixed, and the ring is carefully designed so it can only encircle one toy at a time. On the other hand, to make the game look more attractive, the ring is designed to have the largest radius. Given a
configuration of the field, you are supposed to find the radius of such a ring.

Assume that all the toys are points on a plane. A point is encircled by the ring if the distance between the point and the center of the ring is strictly less than the radius of the ring. If two toys are placed at the same point, the radius of the ring is considered
to be 0.

 

Input

The input consists of several test cases. For each case, the first line contains an integer N (2 <= N <= 100,000), the total number of toys in the field. Then N lines follow, each contains a pair of (x, y) which are the coordinates of a toy. The input is terminated
by N = 0.

 

Output

For each test case, print in one line the radius of the ring required by the Cyberground manager, accurate up to 2 decimal places. 

 

Sample Input

2
0 0
1 1
2
1 1
1 1
3
-1.5 0
0 0
0 1.5
0

 

Sample Output

0.71
0.00
0.75

 

Author

CHEN, Yue

 

Source

ZJCPC2004

 

Recommend

JGShining

 
对于这道题目我首先抱怨一下,超时超的我想哭,原因不是因为算法思路错了,是一开是在对点按照X值从左向右排序的时候用的是qsort,后来改成sort就A了,伤心,等会要好好研究sort和qsort的区别 好了,还是介绍一下最近点对的算法思想吧!

总体思路是递归与分治思想,首先按照点的X值从左到右排序下,然后分成两半,依次求左边和右边的最近点对然后取最下
但是这里问题出现了,如果最近的两个点同时都在分开的两边,那么就简单了,但是如果这两个点分在不同的区域,这下就
麻烦了,这个问题的解决是这个算法正确性和复杂度度关键位置
首先在L和R区间内找到可能是最小点对中的所有点,然后再进行处理
我们这样先在X轴方向全部符合条件的,然后再按照Y轴大小排序,然后开始选择最小的
在按照X轴选择的时候这样,所有到中间位置的X轴距离小于当前在左边和右边找到最小点对的距离的点
然后按照Y轴从小到大排序,然后这里有个鸽巢原理,其实很简单:(转)d是两个半平面各自内,任意两点的最小距离,因此在同一个半平面内,任何两点距离都不可能超过d。   我们又要求P1和P2的水平距离不能超过d,垂直距离也不能超过d,在这个d*2d的小方块内,最多只能放下6个距离不小于d的点。   
然后就没了!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <iostream>
using namespace std;
#define inf 1e8
struct point
{
double x;
double y;
}node[100100];
int my_rec[100100];
int n;
double dis(point &a,point &b)
{
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
int cmp(const point &a,const point &b)
{
return a.x < b.x;
}
bool cmpy(const int &a,const int &b)
{
return node[a].y < node[b].y;
}
double find_min(int l,int r)
{
int i,j,k;
double tmp;
if(l==r)
return inf;
if(l==r-1)
return dis(node[l],node[r]);
double temp1=min(find_min(l,(l+r)/2),find_min((l+r)/2,r));
int mid=(l+r)/2;
k=0;
for(i=l;i<=r;i++)
if(fabs(node[i].x - node[mid].x) < temp1)
my_rec[k++]=i;
sort(my_rec,my_rec+k,cmpy);
for(i=0;i<k-1;i++)
for(j=i+1;j<k &&j< i+7 /*node[my_rec[j]].y-node[my_rec[i]].y < temp1*/;j++)//这里利用上面推论只扫描六个点
{
tmp=dis(node[my_rec[i]],node[my_rec[j]]);
if(tmp < temp1)
temp1=tmp;
}
return temp1;
}
int main()
{
int i,j,k;
while(scanf("%d",&n),n)
{
for(i=0;i<n;i++)
scanf("%lf%lf",&node[i].x,&node[i].y);
if(n==1)
{
printf("0.00\n");
continue;
}
if(n==2)
{
printf("%.2lf\n",dis(node[0],node[1])/2);
continue;
}
sort(node,node+n,cmp);
printf("%.2lf\n",find_min(0,n-1)/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  平面最近点对