Quoit Design
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 41828 Accepted Submission(s): 10871
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.
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
解题思路:第一次用的是暴力求解,超时了,看了人家都用分治写的,不过这题后台数据有些水,可以直接看作最短距离的点是两个点之间坐标x差最小的点,或是坐标y差最小的点.这样也可以过,代码就不给了,重点是用分治法如何实现.
这个分治法的讲解很好,不过代码有些问题http://blog.youkuaiyun.com/hackbuteer1/article/details/7482232.(只需看他对分治的讲解).我一开始以为,对于一个总区间,将其一分为二,只要求出左最小,右最小,,整体最小,比较一下就行了.理解错了,应该是将整体区间不断二分,最后成无数个小的区间,每个区间都应该考虑这三种情况.
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
struct stu{
double x,y;
};
stu node[100000+10];
int cas[100000+10];
int cmpx(stu a,stu b){
if(a.x==b.x)
return a.y<b.y;
else return a.x<b.x;
}
int cmpy(int a,int b){
return node[a].y<node[b].y;
}
double dist(int i,int j){
return sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x)+(node[i].y-node[j].y)*(node[i].y-node[j].y));
}
double merge(int l,int r){
if(l==r)return INF;
else if(l+1==r)return dist(l,r);
int mid=(l+r)>>1;
double d=min(merge(l,mid),merge(mid+1,r));
int i,j,k;
double d1;
k=0;
for(i=l;i<=r;i++){
if(fabs(node[i].x-node[mid].x)<d){
cas[k++]=i;
}
}
sort(cas,cas+k,cmpy);
for(i=0;i<k;i++){
for(j=i+1;j<k&&node[cas[j]].y-node[cas[i]].y<d;j++){
d1=dist(cas[i],cas[j]);
if(d1<d){
d=d1;
}
}
}
return d;
}
int main(){
int n;
while(scanf("%d",&n)&&n){
for(int i=0;i<n;i++){
scanf("%lf%lf",&node[i].x,&node[i].y);
}
sort(node,node+n,cmpx);
printf("%.2lf\n",merge(0,n-1)/2);
}
return 0;
}