Quoit Design


Time Limit: 5 Seconds      Memory Limit: 32768 KB

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

分析:

先将点按照x排序
然后可以可以分为两个区间SL,SR,最近点对的分布情况可以分为3个情况
1.最近点对都在SL
2.最近点对都在SR
3.一个在SR,一个在SL或者相反
1,2种情况都很好解决,直接递归找就可以,假设我们在1,2种情况里面找到了一个最小的距离d,关键就是这第三步,貌似需要n的平方的时间,把左边和右边的两个点都对比一下
其实不用
首先,两边的点,与分割线L的距离超过d的,都可以不看了,其次两个点p1,p2(假设p1左,p2右)与分割线L的距离都小于d,如果他们的纵坐标之差大于d
那么他们也不用看了,这样就是使得可搜索的范围大大减小
然后最重要的来了!!!
对左半部分的,与L的记录在d之内的每个p1来说
右边部分符合上面两个条件的点最多只有6个
原因就是:d是两个半平面各自内,
任意两点的最小距离,因此在同一个半平面内,
任何两点距离都不可能超过d。
我们又要求P1和P2的水平距离不能超过d,
垂直距离也不能超过d,
在这个d*2d的小方块内,最多只能放下6个距离不小于d的点。
因此,第3步总的比较距离的次数不超过n*6。
(嗯~~~也不知道自己说的对不对)
第3步的具体做法是:
3.1删除所有到L的距离大于d的点。 O(n)
3.2把右半平面的点按照纵坐标y排序。 O(nlogn)
3.3对于左半平面内的每个点P1,
找出右半平面内纵坐标与P1的纵坐标的差在d以内的点P2,
计算距离取最小值,算出d3。O(n*6) = O(n)
因为3.2的排序需要O(nlogn),
所以整个算法的复杂度就是O(n((logn)^2))。
整体的思路:
1.把所有的点按照横坐标排序
2.用一条竖直的线L将所有的点分成两等份
3.递归算出左半部分的最近两点距离d1,右半部分的最近两点距离d2,取d=min(d1,d2)
4.算出“一个在左半部分,另一个在右半部分”这样的点对的最短距离d3。
5.结果=min(d1,d2,d3)
 
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define max_v 100005
int n;
struct node
{
double x,y;
}p[max_v];
int a[max_v];
double cmpx(node a,node b)
{
return a.x<b.x;
}
double cmpy(int a,int b)
{
return p[a].y<p[b].y;
}
double dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double slove(int l,int r)
{
if(r==l+)
return dis(p[l],p[r]);
if(l+==r)
return min(dis(p[l],p[r]),min(dis(p[l],p[l+]),dis(p[l+],p[r])));
int mid=(l+r)>>;
double ans=min(slove(l,mid),slove(mid+,r));
int i,j,cnt=;
for(i=l;i<=r;i++)
{
if(p[i].x>=p[mid].x-ans&&p[i].x<=p[mid].x+ans)
{
a[cnt++]=i;
}
}
sort(a,a+cnt,cmpy);
for(i=;i<cnt;i++)
{
for(j=i+;j<cnt;j++)
{
if(p[a[j]].y-p[a[i]].y>=ans)
break;
ans=min(ans,dis(p[a[i]],p[a[j]]));
}
}
return ans;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==)
break;
for(int i=;i<n;i++)
{
scanf("%lf %lf",&p[i].x,&p[i].y);
}
sort(p,p+n,cmpx);
printf("%0.2lf\n",slove(,n-)/2.0);
}
return ;
}
/*
先将点按照x排序
然后可以可以分为两个区间SL,SR
最近点对的分布情况可以分为3个情况
1.最近点对都在SL
2.最近点对都在SR
3.一个在SR,一个在SL或者相反 1,2种情况都很好解决
直接递归找就可以
假设我们在1,2种情况里面找到了一个最小的距离d
关键就是这第三步,貌似需要n的平方的时间,把左边和右边的两个点都对比一下
其实不用
首先,两边的点,与分割线L的距离超过d的,都可以不看了
其次两个点p1,p2(假设p1左,p2右)与分割线L的距离都小于d
如果他们的纵坐标之差大于d
那么他们也不用看了
这样就是使得可搜索的范围大大减小
然后最重要的来了!!!
对左半部分的,与L的记录在d之内的每个p1来说
右边部分符合上面两个条件的点最多只有6个
原因就是:d是两个半平面各自内,
任意两点的最小距离,因此在同一个半平面内,
任何两点距离都不可能超过d。
我们又要求P1和P2的水平距离不能超过d,
垂直距离也不能超过d,
在这个d*2d的小方块内,最多只能放下6个距离不小于d的点。
因此,第3步总的比较距离的次数不超过n*6。
(嗯~~~也不知道自己说的对不对) 第3步的具体做法是:
3.1删除所有到L的距离大于d的点。 O(n)
3.2把右半平面的点按照纵坐标y排序。 O(nlogn)
3.3对于左半平面内的每个点P1,
找出右半平面内纵坐标与P1的纵坐标的差在d以内的点P2,
计算距离取最小值,算出d3。O(n*6) = O(n)
因为3.2的排序需要O(nlogn),
所以整个算法的复杂度就是O(n((logn)^2))。 整体的思路:
1.把所有的点按照横坐标排序
2.用一条竖直的线L将所有的点分成两等份
3.递归算出左半部分的最近两点距离d1,右半部分的最近两点距离d2,取d=min(d1,d2)
4.算出“一个在左半部分,另一个在右半部分”这样的点对的最短距离d3。
5.结果=min(d1,d2,d3) */

ZOJ 2017 Quoit Design 经典分治!!! 最近点对问题的更多相关文章

  1. hdu 1007 Quoit Design (经典分治 求最近点对)

    Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...

  2. HDU1007 Quoit Design 【分治】

    Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  3. poj 1007 Quoit Design(分治)

    Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  4. HDU 1007:Quoit Design(分治求最近点对)

    http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:平面上有n个点,问最近的两个点之间的距离的一半是多少. 思路:用分治做.把整体分为左右两个部分,那么 ...

  5. HDU 1007 Quoit Design(计算几何の最近点对)

    Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...

  6. (hdu1007)Quoit Design,求最近点对

    Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...

  7. HDU 1007 Quoit Design 平面内最近点对

    http://acm.hdu.edu.cn/showproblem.php?pid=1007 上半年在人人上看到过这个题,当时就知道用分治但是没有仔细想... 今年多校又出了这个...于是学习了一下平 ...

  8. hdu 1007 Quoit Design(平面最近点对)

    题意:求平面最近点对之间的距离 解:首先可以想到枚举的方法,枚举i,枚举j算点i和点j之间的距离,时间复杂度O(n2). 如果采用分治的思想,如果我们知道左半边点对答案d1,和右半边点的答案d2,如何 ...

  9. hdu 1007 Quoit Design(分治)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给出n个点求最短的两点间距离除以2. 题解:简单的分治. 其实分治就和二分很像二分的写df ...

随机推荐

  1. 关于YII中layout中的布局和view中数据的关系

    1. view中解释php脚本后显示出的内容会在layout中以<?php echo $content?>输出. 2. view是对应的controller的实例,所以可以通过$this- ...

  2. JS数组与对象的遍历方法大全

    本文简单解析各种数组和对象属性的遍历方法: 原生for循环.for-in及forEach ES6 for-of方法遍历类数组集合 Object.key()返回键名的集合 jQuery的$.each() ...

  3. request对象方法

    1.html <html> <head> <meta http-equiv="Content-Type" content="text/htm ...

  4. 程序控制结构及for循环、foreach循环、迭代器

    结构化程序设计 三种基本控制结构:顺序结构.选择结构.循环结构. 在这种思想的指导下,发展出了面向过程编程方式.面向过程编程的核心是算法+数据结构.算法可以用顺序.选择.循环这三种基本控制结构来实现. ...

  5. apache ftp server的简单入门(properties验证)

    Apache FTPServer:(开源) Apache FTPServer是一个100%纯Java的FTP服务器. 它的设计是基于现有的开放式协议的完整和便携式FTP服务器引擎解决方案.FTPSer ...

  6. centos7 yum安装mysql | mariaDb

    mysql解释: mysql数据库是最常用的一种数据库,下面我来在centos7的迷你版上安装一下mysql.绝对纯净的环境哦 centos:    CentOS-7-x86_64-Minimal-1 ...

  7. Oracle官网登录下载资源账号密码共享

    Oracle帐号:2696671285@qq.com Oracle密码:Oracle123 可爱博主:AlanLee 博客地址:http://www.cnblogs.com/AlanLee 本文出自博 ...

  8. Oracle EBS 创建资产报错

    Solution:设置资产弹性域 随便输入一个值 再冻结

  9. [控件] ChangeColorLabel

    ChangeColorLabel 效果 源码 // // ChangeColorLabel.h // YXMWeather // // Created by XianMingYou on 15/6/2 ...

  10. WinPE ISO制作

    1.安装ADK,然后导出winPE镜像文件和启动文件: 打开 部署和映像工具环境,cd "Windows Preinstallation Environment",运行 copyp ...