Andrew算法求凸包模板

news2024/11/25 7:20:41

前置知识

向量的叉乘: 设 a ⃗ = ( x a , y a , z a ) , b ⃗ = ( x b , y b , z b ) \vec a=(x_a,y_a,z_a), \vec b=(x_b, y_b,z_b) a =(xa,ya,za),b =(xb,yb,zb), 令 a ⃗ \vec a a b ⃗ \vec b b 的叉乘为 c ⃗ \vec c c , 有:
c ⃗ = ∣ i j k x a y a z a x b y b z b ∣ = ( y a z b − z a y b , z a x b − x a z b , x a y b − y a x b ) \vec c=\begin{vmatrix} i & j & k\\ x_a & y_a & z_a\\ x_b & y_b & z_b \end{vmatrix}=(y_az_b-z_ay_b,z_ax_b-x_az_b,x_ay_b-y_ax_b) c = ixaxbjyaybkzazb =(yazbzayb,zaxbxazb,xaybyaxb)
几何意义: ∣ c ⃗ ∣ = ∣ a ⃗ × b ⃗ ∣ = ∣ a ⃗ ∣ ∣ b ⃗ ∣ s i n θ |\vec c|=|\vec a×\vec b|=|\vec a| |\vec b|sin\theta c =a ×b =a ∣∣b sinθ ( θ \theta θ a ⃗ \vec a a b ⃗ \vec b b 向量之间的夹角), 即 ∣ c ⃗ ∣ |\vec c| c 等于 a ⃗ \vec a a , b ⃗ \vec b b 向量构成的平行四边形的面积.
另外 c ⃗ \vec c c 的方向可以用右手螺旋定则判定: 先将 a ⃗ \vec a a b ⃗ \vec b b 移动到同一起点, 右手四指从 a ⃗ \vec a a 方向朝掌心方向旋转到 b ⃗ \vec b b 方向, 则拇指所指方向, 即为结果向量的方向.
在这里插入图片描述

PIP 问题

理解了上述的叉乘的知识, 我们就可以解决PIP这个经典问题的一个子集: 判断一个点是否在一个凸多边形内部. 判断算法的一个伪代码如下:

p 0 , ⋯   , p n − 1 p_0,\cdots,p_{n-1} p0,,pn1为凸多边形边界上的点按逆时针方向遍历形成的一个排列, x x x为待判断的点
for i i i in { 0 , ⋯   , n − 1 } \{0,\cdots,n-1\} {0,,n1}
         \;\;\;\; ( p i p ( i + 1 ) % n → × p ( i + 1 ) % n x → ) ⋅ ( 0 , 0 , 1 ) < 0 (\overrightarrow{p_ip_{(i+1)\%n}} \times \overrightarrow{p_{(i+1)\%n}x})\cdot (0,0,1)<0 (pip(i+1)%n ×p(i+1)%nx )(0,0,1)<0, 则 x x x不在多边形内部
x x x在多边形内部(包括边界上)

求凸包

上面提到的伪代码需要凸多边形边界上的点的一个逆时针的排列, 但如过这个排列没有给出, 这时候就可以用Andrew凸包算法来求这样的一个排列, Andrew算法大致思想如下:

首先把所有点以横坐标为第一关键字,纵坐标为第二关键字排序。显然排序后最小的元素和最大的元素一定在凸包上。而且因为是凸多边形,我们如果从一个点出发逆时针走,轨迹总是「左拐」的,一旦出现右拐,就说明这一段不在凸包上。因此我们可以用一个单调栈来维护上下凸壳。

下面贴一个Andrew算法的模板

inline pair<int, int> vec_ab(pair<int, int> a, pair<int, int> b) {
    return {b.first - a.first, b.second - a.second};
}

inline int cross_prod(pair<int, int> a, pair<int, int> b) {
    return a.first * b.second - a.second * b.first;
}

const int maxn = 2e5 + 5;
pair<int, int> p[maxn], h[maxn];
int stk[maxn];
int used[maxn];


int main() {
// stk[] 是整型,存的是下标
    int n;
    int tp=0 // 初始化栈
    //读入p
    std::sort(p + 1, p + n + 1);  // 对点进行排序
    stk[++tp] = 1;
// 栈内添加第一个元素,且不更新 used,使得 1 在最后封闭凸包时也对单调栈更新
    for (int i = 2; i <= n; ++i) {
        while (tp >= 2 && cross_prod(vec_ab(p[stk[tp - 1]], p[stk[tp]]), vec_ab(p[stk[tp]], p[i])) < 0)//凸包边上的点不算在结果数组内(否则用<0)
            used[stk[tp--]] = 0;
        used[i] = 1;  // used 表示在凸壳上
        stk[++tp] = i;
    }
    int tmp = tp;  // tmp 表示下凸壳大小
    for (int i = n - 1; i > 0; --i)
        if (!used[i]) {
            // ↓求上凸壳时不影响下凸壳
            while (tp > tmp && cross_prod(vec_ab(p[stk[tp - 1]], p[stk[tp]]), vec_ab(p[stk[tp]], p[i])) < 0)//凸包边上的点不算在结果数组内(否则用<0)
                used[stk[tp--]] = 0;
            used[i] = 1;
            stk[++tp] = i;
        }
    for (int i = 1; i < tp; ++i)  // 复制到新数组中去
        h[i] = p[stk[i]];
    int ans = tp - 1; // ans为凸包边上节点数

参考:
https://oi-wiki.org/geometry/convex-hull/
https://zhuanlan.zhihu.com/p/385131501

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/794769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微软对Visual Studio 17.7 Preview 4进行版本更新,新插件管理器亮相

近期微软发布了Visual Studio 17.7 Preview 4版本&#xff0c;而在这个版本当中&#xff0c;全新设计的扩展插件管理器将亮相&#xff0c;并且可以让用户可更简单地安装和管理扩展插件。 据了解&#xff0c;目前用户可以从 Visual Studio Marketplace 下载各式各样的 VS 扩展插…

[DASCTF 2023 0X401七月暑期挑战赛] viphouse复现

这个题想了好久&#xff0c;无果&#xff0c;终于看到WP。照着作了一遍。WP里没有详细解释&#xff0c;所以复现得很辛苦。 程序有5个菜单和1个初始化程序&#xff1a; init 先从os.random读8个字节放到src处login 读入用户名密码&#xff0c;其中密码栈里设的0x40可以读入0x…

【Ap模块EM】08-怎么让Execution Management成为第一个执行的进程?

前面的文章,我们讲述了ubuntu系统上电执行的流程,那么在Ap AutoSAR中Execution Management怎么成为第一个被执行的进程呢额?就是让它取代传统的init进程,成为ubuntu系统第一个执行的进程? 我们可以通过符号链接 symbolic link去实现,这个类似于windows系统中的某个exe文件…

mongoDB详解

mongoDB详解 mongodb是一个nosql数据库&#xff0c;它有高性能、无模式、文档型的特点。他是nosql数据库中功能最丰富&#xff0c;最像关系数据库的。 mongoDb基本介绍 mongodb里面有以下几个核心概念&#xff1a;文档&#xff1a;mongodb数据库的最小数据集&#xff0c;是由…

关于阿里云OSS服务器绑定域名及Https证书

这是一个没有套路的前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e; 主页: oliver尹的主页 格言: 跌倒了爬起来就好&#xff5e; 关于阿里云…

安全学习DAY07_其他协议抓包技术

协议抓包技术-全局-APP&小程序&PC应用 抓包工具-Wireshark&科来分析&封包 TCPDump&#xff1a; 是可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤&#xff0c;并提供and、or、not等逻辑语句来帮助你去掉无用…

TypeError: Failed to fetch dynamically imported module

浏览器报了如下错误&#xff1a; vue文件如下&#xff1a; 错误出现的原因是因为导入的是路径&#xff0c;vue会在该路径下的文件夹搜索所有文件&#xff0c;但是没有找到对应的组件&#xff0c;但是浏览器并不会直接禁止访问&#xff0c;而是在控制台报错&#xff0c;解决办法…

量化交易——python数据分析及可视化

该项目分为两个部分&#xff1a;一是数据计算&#xff0c;二是可视化&#xff0c;三是MACD策略 一、计算MACD 1、数据部分 数据来源&#xff1a;tushare 数据字段包含&#xff1a;日期&#xff0c;开盘价&#xff0c;收盘价&#xff0c;最低价&#xff0c;最高价&#xff0c…

11.python设计模式【责任链模式】

内容&#xff1a;使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。角色&#xff1a; 抽象处理者&#xff08;Handler&#xff09;具体处理…

Unity实现camera数据注入RMP推送或轻量级RTSP服务模块

技术背景 随着技术的不断进步和应用的不断深化&#xff0c;Unity3D VR应用的前景非常广阔&#xff0c;它广泛应用于教育、医疗、军事、工业设计、虚拟数字人等多个领域。 教育领域&#xff1a;Unity3D VR技术可以用来创建虚拟现实教室&#xff0c;让学生能够身临其境地体验课…

微信小程序 事件和语法

属性列表 target&#xff1a;触发事件的对象currentTarget&#xff1a;绑定事件的对象&#xff0c;可能不是由此对象触发而是触发对象冒泡导致触发此事件 微信小程序 事件绑定 <button type"primary" bindtap"btnTapHandler">按钮</button> …

pytorch学习-线性神经网络——softmax回归+损失函数+图片分类数据集

1.softmax回归 Softmax回归&#xff08;Softmax Regression&#xff09;是一种常见的多分类模型&#xff0c;可以用于将输入变量映射到多个类别的概率分布中。softmax回归是机器学习中非常重要并且经典的模型&#xff0c;虽然叫回归&#xff0c;实际上是一个分类问题 1.1分类与…

ORCA优化器浅析——Exploration and Implementation Apply CXform Phase

GPORCA通过规则对表达式做转换&#xff0c;规则分为两类&#xff1a;Exploration&#xff0c;是对逻辑表达式做等价变换的&#xff1b;Implementation&#xff0c;是把逻辑操作符转换为物理操作符。Except the types of operator generated during Exploration (Logical > L…

手机python怎么用海龟画图,python怎么在手机上编程

大家好&#xff0c;给大家分享一下手机python怎么用海龟画图&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1、如何python手机版创造Al&#xff1f; 如果您想在手机上使用Python来创建AI&#xff08;人工智能&#xff09;程序&#xff0…

服务器推送、在线游戏和电子邮件背后的网络协议

之前也聊了不少网络协议这块内容&#xff0c;现在我们将深入探讨关键的网络协议及其在不同应用中的作用。重点在于理解这些协议如何塑造我们在互联网上的通信和互动方式。我们将深入研究以下领域&#xff1a; WebSocket 在之前的讨论中&#xff0c;我们研究了HTTP及其在客户端和…

帮助中心客户服务中的作用与应用

随着互联网的快速发展&#xff0c;越来越多的企业开始寻求更加高效、便捷的客户服务方式&#xff0c;帮助中心的自助服务作为一种新型的客户服务模式&#xff0c;受到了广泛关注。本文将针对帮助中心的自助服务在客户服务中的作用与应用进行深入探讨。 帮助中心在客户服务中的…

scrcpy2.0+实时将手机画面显示在屏幕上并用鼠标模拟点击2023.7.26

想要用AI代打手游&#xff0c;除了模拟器登录&#xff0c;也可以直接使用第三方工具Scrcpy&#xff0c;来自github&#xff0c;它是一个开源的屏幕镜像工具&#xff0c;可以在电脑上显示Android设备的画面&#xff0c;并支持使用鼠标进行交互。 目录 1. 下载安装2. scrcpy的高级…

文本预处理——文本数据分析

目录 文本数据分析中文酒店评价语料获得训练集和验证集的标签数量分布获取训练集和验证集的句子长度分布获取训练集和验证集的正负样本长度散点分布获得训练集和验证集不同词汇总数统计获得训练集上正负的样本的高频形容词词云获得验证集上正负的样本的形容词词云 文本数据分析…

Golang指针详解

要搞明白Go语言中的指针需要先知道3个概念&#xff1a;指针地址、指针类型和指针取值。 指针介绍 我们知道变量是用来存储数据的&#xff0c;变量的本质是给存储数据的内存地址起了一个好记的别名。比如我们定义了一个变量 a : 10 ,这个时候可以直接通过 a 这个变量来读取内存…

IPv6 over IPv4

IPv6 over IPv4隧道简介 IPv6 over IPv4隧道可实现IPv6网络孤岛之间通过IPv4网络互连。由于IPv4地址的枯竭和IPv6的先进性&#xff0c;IPv4过渡为IPv6势在必行。因为IPv6与IPv4的不兼容性&#xff0c;所以需要对原有的IPv4设备进行替换。但是如果贸然将IPv4设备大量替换所需成…