Quoit Design

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
 
Recommend
JGShining
 
     说实话,这篇文章什么意思,我看了半天都没有看懂!不过这不影响做题,这道题实际上就是要求一堆坐标里最短的坐标之间的距离的1/2.
    具体算法在《编程之美》中讲得很详细!







    代码如下:
/*
*最近点对的问题
*/ #include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int SIZE = 100005;
const int L = -1;
const int R = 1; typedef struct
{
int index;
double x;
double y; /*用于记录坐标点*/
}coord; coord num[SIZE], c[SIZE]/*用作辅助数组*/; double getDistance(coord &bi1, coord &bi2) /*求得两点之间的距离*/
{
return sqrt(pow(bi1.x - bi2.x, 2.0) + pow(bi1.y - bi2.y, 2.0));
} bool cmpx(coord &bi1, coord &bi2)
{
if (bi1.x == bi1.x)
return bi1.y < bi2.y;
else
return bi1.x < bi2.x;
} bool cmpy(coord &bi1, coord &bi2)
{
if (bi1.y == bi2.y)
return bi1.x < bi2.x;
else
return bi1.y < bi2.y;
} inline double min(double &bi1, double &bi2, double &bi3)
{
double minLength;
minLength = bi1 > bi2 ? bi2 : bi1;
minLength = minLength > bi3 ? bi3 : minLength;
return minLength;
} inline double minDist(double &bi1, double &bi2)
{
if (bi1 > bi2)
return bi2;
return bi1;
} double divide_conquer(int low, int high) /*分治法求最小距离*/
{
double dis;
int count = high - low;
if (count == 0)
{
return 0;
}
else if (count == 1) /*两个数*/
{
dis = getDistance(num[low], num[high]);
}
else if (count == 2) /*三个数*/
{
double temp1, temp2, temp3;
temp1 = getDistance(num[low], num[low + 1]);
temp2 = getDistance(num[low + 1], num[high]);
temp3 = getDistance(num[low], num[high]);
dis = min(temp1, temp2, temp3);
}
else /*大于三个数的情况*/
{
double leftmin, rightmin, min;
int mid = (low + high) / 2;
int p = 0;
int i, j; leftmin = divide_conquer(low, mid); /*求得左边部分的最小值*/
rightmin = divide_conquer(mid + 1, high); /*求得右边部分的最小值*/
dis = minDist(leftmin, rightmin); /*下面从所有坐标点中找出所有x在leftCoord到rightCoord之间的点*/
for (i = low; i <= mid; i++)
{
double leftCoord = num[mid].x - dis;
if (num[i].x >= leftCoord)
{
c[p].index = L; /*标识属于左边部分*/
c[p].x = num[i].x;
c[p].y = num[i].y;
p++;
}
}
for ( ; i <= high; i++)
{
double rightCoord = num[mid].x + dis;
if (num[i].x <= rightCoord)
{
c[p].index = R; /*标识属于右边部分*/
c[p].x = num[i].x;
c[p].y = num[i].y;
p++;
}
}
sort(c, c + p, cmpy); /*找到的点再从小到大按照y排序一次*/
for (i = 0; i < p; i++)
{
if (c[i].index == L) /*左边的点一个一个地搜索,按照规律,我们只要搜索之后的7个点就可以了*/
{
for (j = 1; (j <= 7) && (i + j < p); j++)
{
if (c[i + j].index == R) /*这个点还必须属于右边*/
{
min = getDistance(c[i], c[i + j]);
if(min < dis)
{
dis = min;
}
}
}
}
}
}
return dis;
} int main ()
{
int n;
while (cin >> n && n != 0)
{
double result = 0; for (int i = 0; i < n; i++)
{
num[i].index = 0;
cin >> num[i].x >> num[i].y;
} sort (num, num + n, cmpx); result = divide_conquer(0, n - 1); printf("%.2lf\n", result / 2);
}
//system ("pause");
return 0;
}

上面的那段代码,说实话,还有很大的问题,不过在杭电上居然也通过了,可见杭电数据之弱!现在发一段修改了bug的代码!这一段代码没有错误!

/*
*最近点对的问题
*/ #include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int SIZE = 100005;
const int L = -1;
const int R = 1; typedef struct
{
int index;
double x;
double y; /*用于记录坐标点*/
}coord; coord num[SIZE], c[SIZE]/*用作辅助数组*/; double getDistance(coord &bi1, coord &bi2) /*求得两点之间的距离*/
{
return sqrt(pow(bi1.x - bi2.x, 2.0) + pow(bi1.y - bi2.y, 2.0));
} bool cmpx(coord &bi1, coord &bi2)
{
if (bi1.x == bi1.x)
return bi1.y < bi2.y;
else
return bi1.x < bi2.x;
} bool cmpy(coord &bi1, coord &bi2)
{
if (bi1.y == bi2.y)
return bi1.x < bi2.x;
else
return bi1.y < bi2.y;
} inline double min(double &bi1, double &bi2, double &bi3)
{
double minLength;
minLength = bi1 > bi2 ? bi2 : bi1;
minLength = minLength > bi3 ? bi3 : minLength;
return minLength;
} inline double minDist(double &bi1, double &bi2)
{
if (bi1 > bi2)
return bi2;
return bi1;
} double divide_conquer(int low, int high) /*分治法求最小距离*/
{
double dis;
int count = high - low;
if (count == 0)
{
return 0;
}
else if (count == 1) /*两个数*/
{
dis = getDistance(num[low], num[high]);
}
else if (count == 2) /*三个数*/
{
double temp1, temp2, temp3;
temp1 = getDistance(num[low], num[low + 1]);
temp2 = getDistance(num[low + 1], num[high]);
temp3 = getDistance(num[low], num[high]);
dis = min(temp1, temp2, temp3);
}
else /*大于三个数的情况*/
{
double leftmin, rightmin, min;
int mid = (low + high) / 2;
int p = 0;
int i, j; leftmin = divide_conquer(low, mid); /*求得左边部分的最小值*/
rightmin = divide_conquer(mid + 1, high); /*求得右边部分的最小值*/
dis = minDist(leftmin, rightmin); /*下面从所有坐标点中找出所有x在leftCoord到rightCoord之间的点*/
for (i = low; i <= mid; i++)
{
double leftCoord = num[mid].x - dis;
if (num[i].x >= leftCoord)
{
c[p].index = L; /*标识属于左边部分*/
c[p].x = num[i].x;
c[p].y = num[i].y;
p++;
}
}
for ( ; i <= high; i++)
{
double rightCoord = num[mid].x + dis;
if (num[i].x <= rightCoord)
{
c[p].index = R; /*标识属于右边部分*/
c[p].x = num[i].x;
c[p].y = num[i].y;
p++;
}
}
sort(c, c + p, cmpy); /*找到的点再从小到大按照y排序一次*/
for (i = 0; i < p; i++)
{
/*错误出现在这里,上面我是只搜索了左边,并且只计算了7个y值比c[i].y大的点到c[i]的距离,
可是实际上y值比c[i].y小的点也有可能与c[i]取得最小值,所以说上面的程序有错误。真正正确
的解答如下,那就是要搜索所有的点,并计算7个y值比c[i].y大的点到c[i]的距离,由于距离是两个
点之间产生的,一个点的y值比另一个点小,那么必然有另一个点的y值比一个点的大,由于这种关系,
从而保证了搜索出来的是最小的距离!
*/
for (j = 1; (j <= 7) && (i + j < p); j++)
{
if (c[i].index != c[i + j].index) /*最小值只可能出现在两个分别属于不同的边的点上*/
{
min = getDistance(c[i], c[i + j]);
if(min < dis)
dis = min;
}
}
}
}
return dis;
} int main ()
{
int n;
while (cin >> n && n != 0)
{
double result = 0; for (int i = 0; i < n; i++)
{
num[i].index = 0;
cin >> num[i].x >> num[i].y;
} sort (num, num + n, cmpx); result = divide_conquer(0, n - 1); printf("%.2lf\n", result / 2);
}
//system ("pause");
return 0;
}

杭电OJ——1007 Quoit Design(最近点对问题)的更多相关文章

  1. hdu 1007 Quoit Design (最近点对问题)

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

  2. HDU 1007 Quoit Design最近点对( 分治法)

    题意: 给出平面上的n个点,问任意点对之间的最短距离是多少? 思路: 先将所有点按照x坐标排序,用二分法将n个点一分为二个部分,递归下去直到剩下两或一个点.对于一个部分,左右部分的答案分别都知道,那么 ...

  3. HDU 1007 Quoit Design(经典最近点对问题)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1007 Quoit Design Time Limit: 10000/5000 MS (Java/Oth ...

  4. C#利用POST实现杭电oj的AC自动机器人,AC率高达50%~~

    暑假集训虽然很快乐,偶尔也会比较枯燥,,这个时候就需要自娱自乐... 然后看hdu的排行榜发现,除了一些是虚拟测评机的账号以外,有几个都是AC自动机器人 然后发现有一位作者是用网页填表然后按钮模拟,, ...

  5. 杭电oj 2095 & 异或^符号在C/C++中的使用

    异或^符号,在平时的学习时可能遇到的不多,不过有时使用得当可以发挥意想不到的结果. 值得注意的是,异或运算是建立在二进制基础上的,所有运算过程都是按位异或(即相同为0,不同为1,也称模二加),得到最终 ...

  6. 用python爬取杭电oj的数据

    暑假集训主要是在杭电oj上面刷题,白天与算法作斗争,晚上望干点自己喜欢的事情! 首先,确定要爬取哪些数据: 如上图所示,题目ID,名称,accepted,submissions,都很有用. 查看源代码 ...

  7. 杭电oj 4004---The Frog Games java解法

    import java.util.Arrays; import java.util.Scanner; //杭电oj 4004 //解题思路:利用二分法查找,即先选取跳跃距离的区间,从最大到最小, // ...

  8. 『ACM C++』HDU杭电OJ | 1415 - Jugs (灌水定理引申)

    今天总算开学了,当了班长就是麻烦,明明自己没买书却要带着一波人去领书,那能怎么办呢,只能说我善人心肠哈哈哈,不过我脑子里突然浮起一个念头,大二还要不要继续当这个班委呢,既然已经体验过就可以适当放下了吧 ...

  9. 杭电oj————2057(java)

    question:A+ B again 思路:额,没啥思路/捂脸,用java的long包里的方法,很简单,只是有几次WA,有几点要注意一下 注意:如果数字有加号要删除掉,这里用到了正则表达式“\\+” ...

随机推荐

  1. Debian(Linux)系统目录简单说明

    bin:基础命令执行档 boot:引导装置器的静态链接文件 dev:设备档 etc:主机特定的系统配置 lib:基本共享库及基本内核模块 mnt:用于临时挂载一个文件系统 proc:系统信息的虚拟目录 ...

  2. Nginx 之六: Nginx服务器的反向代理功能

    一:Nginx作为正向代理服务器: 1.正向代理:代理(proxy)服务也可以称为是正向代理,指的是将服务器部署在公司的网关,代理公司内部员工上外网的请求,可以起到一定的安全作用和管理限制作用,正向代 ...

  3. [LeetCode]题解(python):066-Plus One

    题目来源: https://leetcode.com/problems/plus-one/ 题意分析: 给定一个数组,将数加一,返回新的数组.比如[9,9],返回[1,0,0]. 题目思路: 这道题目 ...

  4. [LeetCode]题解(python):020-Valid Parentheses

    题目来源: https://leetcode.com/problems/valid-parentheses/ 题意分析: 这道题输入一段只包括括号的字符串,判断这个字符串是否已经配对.配对的规则是,每 ...

  5. Visual Studio调试技巧 -- Attach to Process #Reprinted#

    from:http://www.cnblogs.com/lyosaki88/p/3481338.html 一般写完代码时,我们通常会启动调试运行一下看看是否正确,启动运行的方式无非是F5-- Star ...

  6. 转: seajs手册与文档之 -- 模块标识

    目录 模块标识 相对标识 顶级标识 普通路径 文件后缀的提示 模块标识 模块标识是一个字符串,用来标识模块.在 require. require.async 等加载函数中,第一个参数都是模块标识.de ...

  7. tomcat简介之web.xml详解(转)

    http://blog.csdn.net/facepp/archive/2008/04/19/2306602.aspx 位于每个Web应用的WEB-INF路径下的web.xml文件被称为配置描述符,这 ...

  8. android面试题之一

    在接下来的一段时间,我将收集一些常见面试题,综合网上资料加自己测试与理解,将其总结出来和大家分享,里面难免有一些问题,希望大家提出宝贵意见以便及时更正. 一.Activity.Service.Broa ...

  9. Centos6.4下tar包安装最新版Mysql5.6

    1.下载 mysql:http://www.mysql.com/downloads/ (须要注冊ORACLE账号) 版本号:mysql-advanced-5.6.21-linux-glibc2.5-x ...

  10. 百度SiteApp构建网站APP

    现在很多个人网站和企业网站都是传统的Web方式,有没有想过个人/企业网站也能做成APP应用对外宣传呢?专门找人去开发Android和IOS上的APP又太贵,为了赶上移动互联网时髦,我以个人网站试做了一 ...