最近点对问题

2023-11-17

分而治之

题目来源: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

题目大意是从所有的点集中找到最短距离的二分之一即可
刚刚拿到题,直接想到的就是暴力求解,果然还是头脑简单了点,这样做,是可以得解,但是必然exceed running time
查找了一下资料,发现在一本书上有记载一种算法,是用分治的思想解决这类题型的
思想如下:
先将所有点按照x的大小进行排序,再根据x方向将平面中的分成左右两个部分,即Left,Right,并且要求这两个部分的点的个数大致相同,在递归得到了minLeft,minRight后,我们先得到一个可能解ans=min( minLeft,minRight ),但实际上,可能解还存在与Left和Right的中间那个部分,当然,只有这些点对的距离小于ans,才会成为可能解
但是,此处距离的判断也是一个问题,因为这里很有可能会超时
可以反推
要使条件成立,那么可能解的点的横坐标与中轴横坐标差的绝对值必然是小于ans的
最后,再按照y的大小进行升序排序,同理
可能解的纵坐标与中轴纵坐标差的绝对值必然也是小于ans的
书上写了该算法的时间复杂度为O(nlogn)

知道核心思想后的代码

很奇怪为什么WA

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;

struct Point {
	double x;
	double y;
}p[100005], tmp[100005];
double Solution(int left,int right);
double Dis(Point& p1, Point& p2) {
	return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y)*(p1.y-p2.y));
}
double min3(double a, double b, double c) {
	double pre = min(a, b);
	return min(pre, c);
}
bool cmp(Point& p1, Point& p2) {
	if (p1.x == p2.x) {
		return p1.y < p2.y;
	}
	return p1.x < p2.x;
}
bool cmpY(Point& p1, Point& p2) {
	if (p1.y == p2.y) {
		return p1.x < p2.x;
	}
	return p1.y < p2.y;
}
int main() {
	int n;
	scanf("%d", &n);
	while (n != 0) {
		memset(p, 0, sizeof(p));
		for (int i = 0; i < n; i++) {
			scanf("%lf %lf", &p[i].x, &p[i].y);
		}
		sort(p, p + n, cmp);
		printf("%.2lf\n", Solution(0, n - 1)/2);
		scanf("%d", &n);
	}
	return 0;
}
double Solution(int left,int right) {
	if (left == right)return 0;
	else if ((right - left) == 1) { //2points
		return Dis(p[left], p[right]);
	}
	else if ((right - left) == 2) { //3points
		return min3(Dis(p[left], p[left + 1]), Dis(p[left], p[right]), Dis(p[left + 1],
			p[right]));
	}
	int mid = (left + right) >> 1;
	int num = 0;
	double ans = min(Solution(left, mid), Solution(mid + 1, right));
	for (int i = left; i <= mid; i++) {
		if (fabs(p[i].x - p[mid].x) < ans) {
			tmp[num++] = p[i];
		}
	}
	sort(tmp, tmp + num, cmpY);
	for (int i = 0; i < num; i++) {
		for (int j = i+1; j <num; j++) {
			if (tmp[j].y - tmp[i].y < ans) {
				ans = min(ans, Dis(p[i], p[j]));
			}
			else break;
		}
	}
	return ans;
}

最终AC代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;

struct Point {
	double x;
	double y;
}p[100005]/*, tmp[100005]*/;
int tmp[100005];
double Solution(int left,int right);
double Dis(Point& p1, Point& p2) {
	return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y)*(p1.y-p2.y));
}
double min3(double a, double b, double c) {
	double pre = min(a, b);
	return min(pre, c);
}
bool cmp(Point& p1, Point& p2) {
	if (p1.x == p2.x) {
		return p1.y < p2.y;
	}
	return p1.x < p2.x;
}
bool cmpY(int p1,int p2) {
	if (p[p1].y == p[p2].y) {
		return p[p1].x < p[p2].x;
	}
	return p[p1].y < p[p2].y;
}
int main() {
	int n;
	scanf("%d", &n);
	while (n != 0) {
		memset(p, 0, sizeof(p));
		for (int i = 0; i < n; i++) {
			scanf("%lf %lf", &p[i].x, &p[i].y);
		}
		sort(p, p + n, cmp);
		bool flag = true;
		for (int i = 0; i < n-1; i++) {
			if (p[i].x == p[i + 1].x && p[i].y == p[i + 1].y) {
				flag = false;
				break;
			}
		}
		if (!flag)cout << "0.00\n";
		else printf("%.2lf\n", Solution(0, n - 1)/2);
		scanf("%d", &n);
	}
	return 0;
}
double Solution(int left,int right) {
	if (left == right)return 0;
	else if ((right - left) == 1) { //2points
		return Dis(p[left], p[right]);
	}
	else if ((right - left) == 2) { //3points
		return min3(Dis(p[left], p[left + 1]), Dis(p[left], p[right]), Dis(p[left + 1],
			p[right]));
	}
	int mid = (left + right) >> 1;
	int num = 0;
	double ans = min(Solution(left, mid), Solution(mid + 1, right));
	for (int i = left; i <= mid; i++) {
		if (fabs(p[i].x - p[mid].x) < ans) {
			tmp[num++] = i;
		}
	}
	sort(tmp, tmp + num, cmpY);
	for (int i = 0; i < num; i++) {
		for (int j = i+1; j <num; j++) {
			if (p[tmp[j]].y - p[tmp[i]].y < ans) {
				ans = min(ans, Dis(p[tmp[i]], p[tmp[j]]));
			}
			else break;
		}
	}
	return ans;
}

这段代码其实是有借鉴人家的,但是感觉核心理念是一样的啊,只不过将结构体数组换成了int类型的数组,是因为结构体在赋值的时候会消耗大量时间吧?

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

最近点对问题 的相关文章

  • 算法:双指针

    双指针 双指针是一种思想或一种技巧并不是特别具体的算法 具体就是用两个变量动态存储两个结点 来方便我们进行一些操作 通常用在线性的数据结构中 特别是链表类的题目 经常需要用到两个或多个指针配合来记忆链表上的节点 完成某些操作 常见的双指针方
  • 50个c/c++源代码网站

    C C 是最主要的编程语言 这里列出了50名优秀网站和网页清单 这些网站提供c c 源代码 这份清单提供了源代码的链接以及它们的小说明 我已尽力包括最佳的C C 源代码的网站 这不是一个完整的清单 您有建议可以联系我 我将欢迎您的建 议 以
  • Mysql 数据库

    数据库基础 1 什么是数据库 用来存储数据 数据库可在硬盘及内存中存储数据 数据库与文件存储数据的区别 数据库本质也是通过文件来存储数据 数据库的概念就是系统的管理存储数据的文件 数据库介绍 本质就是存储数据的C S架构的socket套接字
  • 算法--将数组分成和相等的多个子数组,求子数组的最大个数

    作者 陈太汉 一个整数数组 长度为n 将其分为m份 使各份的和相等 求m的最大值 比如 3 2 4 3 6 可以分成 3 2 4 3 6 m 1 3 6 2 4 3 m 2 3 3 2 4 6 m 3 所以m的最大值为3 算法 原理的思想是
  • LeetCode83: 删除排序链表中的重复元素

    给定一个已排序的链表的头 head 删除所有重复的元素 使每个元素只出现一次 返回 已排序的链表 示例 1 输入 head 1 1 2 输出 1 2 示例 2 输入 head 1 1 2 3 3 输出 1 2 3 提示 链表中节点数目在范围
  • 白盒测试相关的一些知识

    在白盒测试中 可以使用各种测试方法进行测试 下面这篇文章 可能比较枯燥 如果不乐意读 可以先收藏 如果在你的工作中真遇到白盒测试的话 可以回过头再来看看 还是值得读一读 一般来说 白盒测试时要考虑以下5个问题 1 测试中尽量先用自动化工具来
  • 第二十八节、基于深度学习的目标检测算法的综述(附代码,并附有一些算法英文翻译文章链接))...

    在前面几节中 我们已经介绍了什么是目标检测 以及如何进行目标检测 还提及了滑动窗口 bounding box 以及IOU 非极大值抑制等概念 这里将会综述一下当前目标检测的研究成果 并对几个经典的目标检测算法进行概述 本文内容来自基于深度学
  • 4399 C++笔试题

    1 写出一个函数 取到链表中倒数第二个节点 双链表 node getSec List mylist return mylist m tail gt m prev m prev为链表前指针 单链表 node getSec List mylis
  • 链表和线性表的优缺点

    链表和线性表的优缺点 作为我们最先接触的两个数据结构 链表和线性表的优缺点都较为明显 并且二者互相补足 文章目录 链表和线性表的优缺点 线性表 线性表的组成 线性表的缺点 线性表的优点 链表 链表的组成 链表的优点 链表的缺点 总结 线性表
  • 数据结构与算法学习总结(六)——字符串的模式匹配算法

    基本概念 字符串是一种特殊的线性表 即元素都是 字符 的线性表 字符是组成字符串的基本单位 字符的取值依赖于字符集 例如二进制的字符集为0 1 则取值只能为 0 1 再比如英语语言 则包括26个字母外加标点符号 例如 abcde 就是一个字
  • 亚利桑那州立大学周纵苇:研习 U-Net ——现有的分割网络创新

    雷锋网AI研习社按 经典的 Encoder Decoder 结构在目标分割问题中展现出了举足轻重的作用 然而这样一个相对固定的框架使得模型在感受野大小和边界分割精度两方面很难达到兼顾 本次公开课 讲者以 U Net 为案例分析 总结现有的分
  • 如何根据链表节点数据大小对链表节点进行排序

    对链表排序有两种方法 1 比较了两个节点的大小后 对指针进行改变 从而交换节点的顺序 2 比较了两个节点的大小后 只交换数据域 而不改变指针 从而交换节点的顺序 第二种办法比较简单 本文主要对第二种方法进行讲解 链表节点排序算法 采用 冒泡
  • 数据结构之图的两种遍历实现(C语言版)

    上一期文章分享完了图的两种遍历方式 也是两种很重要的算法 DFS和BFS 这两种算法的应用和重要性我就不多说了 内行的人懂的都懂 今天这文章重要就是来上机实现这两种算法 又由于这两种算法都可以由邻接矩阵和邻接表来表示 博主分享的代码都是上机
  • 算法问题实战策略

    算法问题实战策略 基本信息作者 韩 具宗万 译者 崔盛一出版社 人民邮电出版社ISBN 9787115384621上架时间 2015 2 4出版日期 2015 年3月开本 16开页码 738版次 1 1 内容简介 算法问题实战策略 本书收录
  • 数据结构与算法-列表(双向链表)设计及其排序算法

    0 概述 本文主要涵盖列表 双向链表 的设计及其排序算法的总结 列表是一种典型的动态存储结构 其中的数据 分散为一系列称作节点 node 的单位 节点之间通过指针相互索引和访问 为了引入新节点或删除原有节点 只需在局部调整少量相关节点之间的
  • 时间复杂度+常见复杂度解释

    前言 算法的效率 虽然计算机能快速的完成运算处理 但实际上 它也需要根据输入数据的大小和算法效率来消耗一定的处理器资源 要想编写出能高效运行的程序 我们就需要考虑到算法的效率 算法的效率主要由以下两个复杂度来评估 时间复杂度 评估执行程序所
  • 区块链中的哈希算法

    区块链中的密码学 密码学在区块链中的应用主要有两个 哈希算法与非对称加密算法 这次主要对哈希算法进行详细的说明 哈希算法 哈希算法的特点有 1 输入可以为任意大小的字符串 2 产生固定大小的输出 3 可以在合理的时间内算出输出值 若要满足密
  • 二叉树结构的建立与遍历

    实验项目 1 编写建立二叉树的二叉链表存储结构 左右链表示 的程序 并以适当的形式显示和保存二叉树 2 完成二叉树的7种遍历操作 3 给定一个二叉树 编写算法完成下列应用 1 判断其是否为完全二叉树 2 求二叉树中任意两个结点的公共祖先 输
  • 【数据结构】单链表的定义和操作

    目录 1 单链表的定义 2 单链表的创建和初始化 3 单链表的插入节点操作 4 单链表的删除节点操作 5 单链表的查找节点操作 6 单链表的更新节点操作 7 完整代码 嗨 我是 Filotimo 很高兴与大家相识 希望我的博客能对你有所帮助
  • 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题 如何实现多个升序链表的合并 这是 LeetCode 上的一道原题 题目具体如下 用归并实现合并 K 个升序链表 LeetCode 23 合并K个升序链表 给你一个链表数组 每个链表都已经按升序排列 请你将所有链表合并到

随机推荐

  • 二维多孔介质图像的粒度分布研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 使用流域分割算法对岩石二维二值图像进行粒度
  • Scala深入浅出——从Java到Scala

    本文适合有一定Java基础的 并想系统学习Scala的小伙伴借鉴学习 文章有大量实例 建议自己跑一遍 Scala深入浅出 从Java到Scala Scala 一 介绍 1 什么是Scala 2 特点 3 安装 二 Scala特点 三 sca
  • SecureCRT9.1高亮配色设置

    参考 http zh cjh com qita 1623 html https download csdn net download qq 45698138 88310255 spm 1001 2014 3001 5503 1 创建文件co
  • fork的例子

    以下是下列代码的头文件 forks c Examples of Unix process control include
  • Ruoyi-cloud集成Sa-Token SSO单点登录

    文章目录 服务端 客户端前端 客户端后端 https github com dromara Sa Token Sa Token SSO 模式三 修改本地hosts 127 0 0 1 sa sso server com 127 0 0 1
  • ionic3代码压缩和apk优化

    我们在做ionic打包的时候 通常执行这条命令 ionic cordova build android release prod 使用这个命令生成的apk是ionic项目导出的最优化的apk 但是如果还想继续压缩 那么还可以借助Androi
  • Unity 空气墙Shader

    废话不多说 先上效果图 具体代码如下 Shader Hidden AirWall Properties Color Color Color 1 1 1 1 颜色 Interval Interval float 10 间隔 SubShader
  • springmvc注解和参数传递

    一 SpringMVC注解入门 创建web项目 在springmvc的配置文件中指定注解驱动 配置扫描器 Xml代码 收藏代码
  • FFmpeg 实战指南

    文章目录 表达式 滤镜效果 zoompan 中心视距由远及近 中心视距由近及远 水平视距从左到右 水平视距从右到左 垂直视距从上到下 垂直视距从下到上 rotate 顺时针旋转 PI 6 弧度 逆时针旋转 PI 6 弧度 顺时针旋转 45
  • 【Flink】处理函数Process

    目录 处理函数 基本处理函数 ProcessFunction 处理函数的功能 ProcessFunction解析 处理函数的分类 按键分区处理函数 KeyedProcessFunction 定时器Timer 和定时服务 TimerServi
  • 几种css炫酷背景欣赏

    这里为大家带来几种表现惊人的css背景效果 纯css表现效果 有桌布效果 星空效果 心形效果 砖墙效果等 请欣赏 background radial gradient rgba 255 255 255 0 0 rgba 255 255 25
  • 2020-10-29 org.apache.commons.lang3.StringUtils

    public static void TestStr null 和 操作 判断是否Null 或者 System out println StringUtils isEmpty null System out println StringUt
  • 基于神经网络的模式识别

    一 项目设计的目的 通过构建BP网络和离散Hopfield网络模式识别实例 输出稳定结果 二 相关原理知识介绍 BP学习算法是通过反向学习过程使误差最小 其算法过程从输出节点开始 反向地向第一隐含层 即最接近输入层的隐含层 传播由总误差引起
  • Ceres Solver从零开始手把手教学使用

    目录 一 简介 二 安装 三 介绍 四 Hello Word 五 导数 1 数值导数 2解析求导 六 实践 Powell函数 一 简介 笔者已经半年没有更新新的内容了 最近学习视觉SLAM的过程中发现自己之前学习的库基础不够扎实 Ceres
  • 用JS获取移动设备信息

    获取设备信息少不了的一个JS脚本就是 mobile detect js 如图第二个script链接就是mobile detect js的网上链接 它的官方链接我给大家放在这里了 mobile detect js官方地址https www m
  • 【毕业设计】深度学习图像语义分割算法研究与实现 - python 机器视觉

    文章目录 0 前言 2 概念介绍 2 1 什么是图像语义分割 3 条件随机场的深度学习模型 3 1 多尺度特征融合 4 语义分割开发过程 4 1 建立 4 2 下载CamVid数据集 4 3 加载CamVid图像 4 4 加载CamVid像
  • SpringBoot学习笔记35——实现List校验@Validated

    在 Controller 类上 加上 Validated 在需要校验的参数上加上 Valid 就可以校验list里的实体类的属性 还需要在统一异常处理类中添加异常处理 参数校验异常类 param exception return autho
  • redis未授权访问漏洞利用+redis日志分析

    redis未授权访问漏洞利用 redis日志分析 redis未授权访问 远程连接redis kali redis cli h IP redis常用语句 set key value 设置键值对 get key 获得值 incr intkey
  • 超分辨率学习记录

    超分辨率学习记录 超分定义 经典模型 前上采样 SRCNN 后上采样 FSRCNN 这篇博客主要内容来自于天池网站的超分辨率理论基础 同时对于其中涉及的学术名词也进行了解释 作为自己学习的记录 注 所有名词右上方带 的下面都有详细解释 博客
  • 最近点对问题

    分而治之 题目来源 Quoit Design Problem Description Have you ever played quoit in a playground Quoit is a game in which flat ring