ZOJ 2017 Quoit Design 经典分治!!! 最近点对问题
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
分析:
然后可以可以分为两个区间SL,SR,最近点对的分布情况可以分为3个情况
1.最近点对都在SL
2.最近点对都在SR
3.一个在SR,一个在SL或者相反
其实不用
首先,两边的点,与分割线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.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)
#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 经典分治!!! 最近点对问题的更多相关文章
- hdu 1007 Quoit Design (经典分治 求最近点对)
Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...
- HDU1007 Quoit Design 【分治】
Quoit Design Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- poj 1007 Quoit Design(分治)
Quoit Design Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- HDU 1007:Quoit Design(分治求最近点对)
http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:平面上有n个点,问最近的两个点之间的距离的一半是多少. 思路:用分治做.把整体分为左右两个部分,那么 ...
- HDU 1007 Quoit Design(计算几何の最近点对)
Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...
- (hdu1007)Quoit Design,求最近点对
Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...
- HDU 1007 Quoit Design 平面内最近点对
http://acm.hdu.edu.cn/showproblem.php?pid=1007 上半年在人人上看到过这个题,当时就知道用分治但是没有仔细想... 今年多校又出了这个...于是学习了一下平 ...
- hdu 1007 Quoit Design(平面最近点对)
题意:求平面最近点对之间的距离 解:首先可以想到枚举的方法,枚举i,枚举j算点i和点j之间的距离,时间复杂度O(n2). 如果采用分治的思想,如果我们知道左半边点对答案d1,和右半边点的答案d2,如何 ...
- hdu 1007 Quoit Design(分治)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 题意:给出n个点求最短的两点间距离除以2. 题解:简单的分治. 其实分治就和二分很像二分的写df ...
随机推荐
- canvas框架::createjs入门
createjs是一个轻量级的框架,稍微有点时间和耐心,就可以把全部源代码都看一遍,毕竟只有三十几个js文件.地址:http://www.createjs.com/ 开发createjs的动画或游戏, ...
- js返回一组日期中最近连续的天数
用js获取一组日期(并把当天算入)中连续的天数 刚开始可能想到单纯的比较日期大小判断连续, 而又有大小月,平闰年这些因素,还是时间戳来的安全; 首先得有一组日期,比如: var arr = [ '20 ...
- JSP 插入到数据库的数据出现 “SQLServerException: 将截断字符串或二进制数据” 错误解决方案
最近在编写一个小型基于的jsp系统开发.掌握数据库一直感觉还不错.但是今天就出现了一个问题困扰我大半天.后来本来准备睡觉,但是觉得今天不解决这个问题恐怕晚上是“彻夜难眠啊”!!于是打开电脑,又开始捣腾 ...
- JavaWeb学习—思维导图
- Android屏幕适配工具
这里需要用到一个jar包,下载拿到这个jar包后直接双击就可以生成市场大部分主流屏幕尺寸了.然后只要把生成好的xml尺寸文件拷贝到相应的value文件中即可.很方便,以后再也不用担心适配繁琐的问题了. ...
- Android:Building " " Gradle project info 问题
Android Studio新建或者打开项目的时候,一直卡在Building "" Gradle project info 进度上不动,猜测是网络原因下载gradle不成功. 两种 ...
- Material适配1 - 入门篇
版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/4493384.html 随着Material Design的普 ...
- python中的字符串编码问题——2.理解ASCII码、ANSI码、Unicode编码、UTF-8编码
ASCII码:全名是American Standard Code for Information Interchange,ASCII码中,一个英文字母(不分大小写)占一个字节的空间,范围0x00~0x ...
- spring boot(14)-pom.xml配置
继承spring-boot-starter-parent 要成为一个spring boot项目,首先就必须在pom.xml中继承spring-boot-starter-parent,同时指定其版本 & ...
- MySQL无法启动、服务没有报告任何错误&初次登陆错误的解决
先以管理员身份运行cmd(右键单击左下角win菜单) 输入mysqld -install,net start mysql,下图是返回结果.报错情况以及修正之后的全过程 启动失败之后输入mysqld - ...