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 ...
随机推荐
- springboot 文件上传和下载
文件的上传和下载 1.文件上传 html页面代码如下 <form method="post" action="/file/upload1" enctype ...
- drupal7 判断用户是否具有某个权限
user_access() 具体用法可参考http://www.drupalla.com/node/857
- Vue 框架-03-键盘事件、健值修饰符、双向数据绑定
Vue 框架-03-键盘时间及健值修饰符 一.键盘事件,当按键盘时,在控制台输出提示 html 源码: <!DOCTYPE html> <html> <head> ...
- Pig模式
Pig中的模式可以是用户显示声明的,也可以是Pig通过用户的使用方式猜测的. Pig对模式的认知在Pig Latin脚本执行的不同阶段可能是不同的. 下面的语句,用户显示声明了模式:3个字段, ...
- Re:LieF ~親愛なるあなたへ~ 后感
遇到烦恼就能有个安逸的地方逃避.这个想法真好.遗憾现实并不能如此.若是觉得这款纯爱作有些许的感人之处,那定时因为受众玩家正在通过玩游戏来逃避现实.“虚拟世界的感情是真实的.” 这件事在旁人看来或许是笑 ...
- winform listbox 使用DrawMode使用OwnerDrawVarialbe或OwnerDrawFixed无水平滚动条
因为需要使用DrawMode自行DrawItem,所以需要将DrawMode设置为OwnerDrawVarialbe或OwnerDrawFixed模式,代码如下: private void listB ...
- 洛谷P1064 金明的预算方案
题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱就行”. ...
- [SQLServer] 内存占用查看
SELECT (physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB, (locked_page_allocations_kb/1 ...
- a标签 按钮化使用
a标签 按钮化使用 a href="javascript:void(0);" onclick="js_method()" a href="javasc ...
- 【Redis】命令学习笔记——列表(list)+集合(set)+有序集合(sorted set)(17+15+20个超全字典版)
本篇基于redis 4.0.11版本,学习列表(list)和集合(set)和有序集合(sorted set)相关命令. 列表按照插入顺序排序,可重复,可以添加一个元素到列表的头部(左边)或者尾部(右边 ...