杭电OJ——1007 Quoit Design(最近点对问题)

2023-10-31

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;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • poj 2155 Matrix

    Problem poj org problem id 2155 vjudge net contest 146952 problem A Meaning 一个 N N 的矩阵 A 初始时全部值为 0 有两种操作 1 C x1 y1 x2 y2
  • 【刷题】华为笔试面试机考 [HJ5] - 进制转换

    题目地址 点击跳转 题目描述 写出一个程序 接受一个十六进制的数 输出该数值的十进制表示 输入描述 输入一个十六进制的数值字符串 注意 一个用例会同时有多组输入数据 请参考帖子https www nowcoder com discuss 2
  • 【刷题】华为笔试面试机考 [HJ29] - 字符串加解密

    题目地址 点击跳转 题目描述 1 对输入的字符串进行加解密 并输出 2 加密方法为 当内容是英文字母时则用该英文字母的后一个字母替换 同时字母变换大小写 如字母a时则替换为B 字母Z时则替换为a 当内容是数字时则把该数字加1 如0替换1 1
  • 鸽巢原理(初识)(纯算法)

    http www docin com p 1352185354 html 一 什么是 鸽巢原理 抽屉原理 若把n个物体放在n 1个抽屉中 至少有一个抽屉中放了两个物体 二 特点 只能用于解决存在性问题 三 例题 例一 在边长为1的三角形放5
  • scanf("%s")读取字符串

    关于c语言字符串读取 可以看出 读取的起始位置就是自己传入的位置 如果写成scanf s a 则默认就是起始地址 这里需要注意的是 由于scanf s 遇到空白符停止的特点 输出数组时候需要指定起始地址为读入时候的地址 否则没有输出 求长度
  • Kattis Doors

    Problem open kattis com problems doors vjudge net contest 183886 problem B Reference 点到线段的最短距离算法 Meaning 有两个球 Alex 和 Bob
  • hdu 1069 Monkey and Banana

    Problem acm hdu edu cn showproblem php pid 1069 Reference www cnblogs com kuangbin archive 2011 08 04 2127291 html 题意 给
  • csu 1803 2016 2016湖南省赛 A

    Problem acm csu edu cn csuoj problemset problem pid 1803 vjudge net contest 161962 problem A Reference www cnblogs com w
  • LightOJ 1045 Digits of Factorial

    Problem acm hust edu cn vjudge problem visitOriginUrl action id 26765 分析 在base进制下 pow base x 表示最小的 x 1 位数 pow base x 1 表
  • 杭电OJ_(2043)密码

    Problem Description 网上流传一句话 常在网上飘啊 哪能不挨刀啊 其实要想能安安心心地上网其实也不难 学点安全知识就可以 首先 我们就要设置一个安全的密码 那什么样的密码才叫安全的呢 一般来说一个比较安全的密码至少应该满足
  • c编程:求出4×4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和。

    求出4 4矩阵中最大和最小元素值及其所在行下标和列下标 求出两条主对角线元素之和 include
  • stl_set

    begin 返回指向第一个元素的 迭代器 clear 清除所有元素 size 集合中元素的数目 count 返回某个值元素的个数 empty 如果集合为空 返回true 真 end 返回指向最后一个元素之后的迭代器 不是最后一个元素器 in
  • poj 2155 Matrix

    Problem poj org problem id 2155 vjudge net contest 146952 problem A Referencd www cnblogs com gj Acit p 3258880 html Mea
  • hdu 1255 覆盖的面积

    Problem acm hdu edu cn showproblem php pid 1255 Reference hdu 1255 覆盖的面积 矩形面积并 矩形面积交 矩形周长并 线段树 扫描线总结 Meaning 给出 n 个矩形 求它
  • hdu 6208 The Dominator of Strings

    Problem acm hdu edu cn showproblem php pid 6208 Meaning 有 n 个字符串 问是否能找到其中一串 使得其它串都是它的子串 Analysis 如果存在这个串 那它一定是 n 个中的最长串
  • gym 101505 CTU Open Contest 2016 G Orchard Division

    Problem codeforces com gym 101505 attachments vjudge net contest 187874 problem G Meaning 一个 m m 的网格 长 宽下标 0 m 1 里有 n 个点
  • 回溯--深度优先搜索(图的M着色问题 poj1129)

    回溯 图的m着色问题 题目描述 给定无向连通图G V E 和m种不同的颜色 用这些颜色为图G的各顶点着色 每个顶点着一种颜色 是否有一种着色法使G中相邻的两个顶点有不同的颜色 这个问题是图的m可着色判定问题 若一个图最少需要m种颜色才能使图
  • Summer Holiday HDU - 1827 强连通分量+缩点

    To see a World in a Grain of Sand And a Heaven in a Wild Flower Hold Infinity in the palm of your hand And Eternity in a
  • UVa 12504 Updating a Dictionary

    Problem uva onlinejudge org index php option com onlinejudge Itemid 8 page show problem problem 3948 题意 貌似是模拟 Source Cod
  • kuangbin的模板

    直接链接 间接链接

随机推荐

  • LaTeX各种算法排版

    1 首先在导言区加入语句 usepackage algorithm usepackage algorithmic 2 例1 begin algorithm caption A label alg A begin algorithmic ST
  • AUTOSEMO“恒以致远,共创共赢”主题研讨会圆满落幕

    2023年8月31日 中国汽车工业协会软件分会中国汽车基础软件生态标委会 简称 AUTOSEMO 与天津市西青区人民政府联合主办 北京经纬恒润科技股份有限公司承办的 恒以致远 共创共赢 主题研讨会在天津隆重召开 本次研讨会是AUTOSEMO
  • vue2.0使用less 创建全局的颜色变量,配置主题色

    1 使用场景 项目中需要统一配置前端的主题样式 我们可以使用less创建 theme colors rgba 54 174 149 1 变量 供全局调用 2 安装依赖 cnpm install less less loader save 安
  • 【Android】WebView控件最全使用解析

    WebView控件最全使用解析 一 WebView 概述 二 WebView使用基础篇 2 1添加方式 2 2 加载远程网页 2 3 加载本地网页 2 4 加载HTML片段 2 5 WebView 常用方法 三 WebView 进阶篇 3
  • Android--Recovery模块之恢复出厂设置

    一 在进行详细流程分析之前 先看一下几个重要概念 一 Recovery的工作需要整个软件平台的配合 从架构角度看 有三个部分 1 Main system 用boot img启动的Linux系统 Android的正常工作模式 2 Recove
  • 【MyBatis】自定义resultMap三种映射关系

    目录 一 一对一映射 One to One 1 1 表关系 1 2 resultMap设置自定义映射 二 一对多映射 One to Many 2 1 创建实体 2 2 级联方式处理映射关系 2 3 定义SQL 2 4 OrderMapper
  • jquery 购物车飞入特效--全网最简单

    有个插件 jquery fly js 可以搞定 好象特点之一是有抛物线效果 如果要求不高 可以看看我这个 其实也是在网上看到的 作了些改进 三个元素 被点击的div 飞翔的小红点 装小红点的div 购物车 div 被点击的 div div
  • (一)@Input属性讨论

    Input Declares a data bound input property Angular automatically updates data bound properties during change detection 大
  • PAT C入门题目-7-111 输出学生成绩 (20 分)(动态内存分配)

    7 111 输出学生成绩 20 分 本题要求编写程序 根据输入学生的成绩 统计并输出学生的平均成绩 最高成绩和最低成绩 建议使用动态内存分配来实现 输入格式 输入第一行首先给出一个正整数N 表示学生的个数 接下来一行给出N个学生的成绩 数字
  • vue3+uniapp+TS+Vite+uView-plus(uniapp-nutui)微信小程序模板搭建

    官网下载目录结构 DCloud uni preset vue 码云 开源中国 gitee com 下载zip压缩包即可 目录 一 依赖下载 二 运行 三 vite config json文件修改 四 uView plus组件库加载 1 安装
  • Android Studio之BuildConfig类

    转自 http blog csdn net lvxiangan article details 71601451 Android Studio开发中 把一个module输出打包为jar文件 我们会发现里面多了一个BuildConfig类 但
  • vue中慎用style的scoped属性

    在vue组件中 在style标签上添加scoped属性 以表示它的样式作用于当下的模块 很好的实现了样式私有化的目的 这是一个非常好的机制 但是为什么要慎用呢 在实际业务中我们往往会对公共组件样式做细微的调整 如果添加了scoped属性 那
  • 前后端通过局域网对接

    因为前后端分离写项目 后端同学在隔壁宿舍 我们通过连他的热点来进行前后端的对接 第一步 关闭防火墙 第二部 找到自己ip地址 无线局域网Ipv4地址 然后前后端在 cmd中 通过 ping 加上地址可以连接成功 然后就可以访问后端的接口了
  • Linux与Windows:操作系统之争及个人体验比较

    在当今数码化的世界中 操作系统扮演着关键的角色 Linux和Windows作为最受欢迎和广泛使用的操作系统之一 具有不同的特点和优势 作为一个AI模型 我虽然没有真正的使用经验 但我可以就这两个操作系统进行比较 并提供一些观点供您参考 Li
  • 利用注册表修改3389端口

    步骤 打开 开始 运行 输入 regedit 打开注册表 进入以下路径 HKEY LOCAL MACHINE SYSTEM CurrentControlSet Control Terminal Server Wds rdpwd Tds tc
  • 1060- 礼物的最大价值

    题目如下 在一个 m n 的棋盘的每一格都放有一个礼物 每个礼物都有一定的价值 价值大于 0 你可以从棋盘的左上角开始拿格子里的礼物 并每次向右或者向下移动一格 直到到达棋盘的右下角 给定一个棋盘及其上面的礼物的价值 请计算你最多能拿到多少
  • VMware 搭建私有云

    我们的目的是在VMware workstation 上安装Centos 7系统 并配置用远程桌面访问虚拟机 在虚拟机上安装Centos 7 首先按照老师给出的博客 VirtualBox 安装 Centos 7 笔记 进行安装 博主使用的是v
  • MPU6050 加速度计和陀螺仪传感器与 Arduino 连接

    MPU6050 加速度计和陀螺仪传感器与 Arduino 连接 前言 MPU6050 模块引脚 MPU6050 模块组成 MPU6050陀螺仪传感器模块电路图 MPU6050模块如何工作 MEMS加速度计如何工作 MEMS陀螺仪如何工作 常
  • 刷题day67:零钱兑换II(完全背包开始)

    题意描述 给你一个整数数组 coins 表示不同面额的硬币 另给一个整数 amount 表示总金额 请你计算并返回可以凑成总金额的硬币组合数 如果任何硬币组合都无法凑出总金额 返回 0 假设每一种面额的硬币有无限个 题目数据保证结果符合 3
  • 杭电OJ——1007 Quoit Design(最近点对问题)

    Quoit Design Problem Description Have you ever played quoit in a playground Quoit is a game in which flat rings are pitc