凸包, 概念

article/2025/7/5 12:57:20

catalog

  • 凸包
    • 算法1 `O(n * m)`
    • 算法2 `O(n * logN)` Andrew安德鲁算法
      • 凸包模板

凸包

通常上讲
平面上有很多的点, 用一个 皮筋 圈住 这所有的点, 此时这个 皮筋, 就是 这些点的 凸包

数学上讲
性质1: 凸包上, 任何一条边 他所在的直线 即为L, 则所有的点 都在直线L 的 同一侧
在这里插入图片描述

比如以凸包上的 AB边 为例, 所有的点: (要么在AB直线上) (要么都在同一侧比如以A->B这个方向来看, 都在该向量的 右侧)


性质2 (重点):

  • 由于凸包是一个环, 存在(顺时针 和 逆时针) 两个方向, 不妨先统一规定下 方向, 比如以 顺时针来看.

  • 凸包上 任意连续的3个点 ABC, 由于是顺时针, 我们看 A -> B 这个方向的 向量
    你让这个向量, 以 A点 为中心 顺时针的旋转, 直到他 遇到 第一个C, 则, 该点C, 就是 继AB后 凸包上的 下一个点


性质3: 还是以 顺时针为例

  • 对于凸包上的 任意一个点 A (即, 已知, A点 是凸包上的点), 设B点是 A点 顺时针 的 下一个点. 记其他的(除了AB点) 的所有点 为Set集合
    记: A -> B向量 为 vec1, A -> Set 所构成的 所有向量 为 vec2
    则一定有: vec1 * vec2 (叉积) <= 0
  • 从上图可以看出, 已知A点 是凸包上的点
    假设C点, 是A点 顺时针的 下一个点;
    但是, 存在B点, 使得: A->C * A->B 的叉积 > 0; 说明: C点, 不是A点的 下一点
    A->B向量 * A->other向量 的叉积 均是 <= 0 的. 说明: B点, 是A点的 下一个凸包上的点

这个性质, 是我们 获取凸包 (即获取凸包上所有的点), 算法的 核心依据.
因为这个性质 告诉我们, 如何通过 一个 凸包上的点, 找到 他的 下一个凸包上的点.


算法1 O(n * m)

统一以: 顺时针 为方向

先获取一个凸包上的点Start
O(n)遍历, 找到 对{x,y}sort的 最小/最大的点 无需sort, O(n)cmp即可
这个点, 可以证明, 他一定是凸包上的, 因为他是 极值点;

已知一个凸包上的点A, 如何得到他的下一个点B

Start点;  ' 也就是上面的, 凸包的Start点 '
A点;  ' 已经得到的凸包上的 顺时针的 最后一个点 '
B点 = 任意一个 {非A}的点
FOR( C : 所有点){if( {A->C向量} 是在 {A->B向量} 左侧){B = C;   ' 更新B '}
}
if( B == Start){  ' 这里很重要, 说明 又回到起点了 'break; 
}

具体代码

__VE< int> convex;
convex.clear();
{int j = 0;__FOR(i, 1, n-1, 1){if( -1 == Db_cmp( points[i].x, points[j].x, eps)){j = i;}else if( 0 == Db_cmp( points[i].x, points[j].x, eps) &&-1 == Db_cmp( points[i].y, points[j].x, eps)){j = i;}}convex.__PB( j); ' Start点 '
}while( true){int pre = convex[ convex.size()-1];int cur;__FORC(i, points){if( i != pre){cur = i;break;}}__FORC(i, points){const auto & pa = points[ pre];const auto & pb = points[ cur];Vector2D< double> vec(pa, pb); // 如何把这个double, 自动推导Vector2D< double> nex(pa, points[ i]);if( Db_sign( vec.cross( nex), eps) == 1){cur = i;}}if( cur == convex.at( 0)){break;}else{convex.__PB( cur);}
}

在这里插入图片描述
凸包上有多少点, 就会循环多少次. 每次得到一个新的点.

算法2 O(n * logN) Andrew安德鲁算法

对所有点 进行sort后, 令Mi = points.beign(), Ma = points.end()
可以证明, Mi 和 Ma 一定都在 凸包上

在这里插入图片描述
其中绿色的标号, 是将这个点 sort后 的次序.

将这个凸包, 分为 上下两个部分;
一部分是: Mi 1 3 5 Ma 上面的; 一部分是: Mi 2 4 6 Ma 下面的;


先求第一部分Mi 1 3 5 Ma:

  • 之前的算法是: 求每个点, 都是通过O(n); 即总时间是: O(n * k); 此时, 我们可以做到: O(n), 即一次线性扫描 得到1 3 5这些点

  • 以前做法, 做不到 线性; 因为存在这种情况:
    在这里插入图片描述
    由于次序是未知的; 比如次序是: A D B C
    当你遍历到D时, 此时凸包是: A D;
    然后遍历到B时, 会 顶替掉 D; 即凸包为: A B
    此时, 就不对了 因为, D是凸包上的点; 你给扔掉了; 又因为是线性扫描, D不会再遍历到;

    但是, 很重要的一点是: 在sort后, 不会出现这个问题.
    比如说: (当前点cur) 顶替掉了 (pre点) 即cur向量 在 pre向量 的左侧
    在这里插入图片描述
    经分析, 以上两种情况; pre, 都不会是 (当前的 上凸包) 中的
    即, 经过线性扫描, 获取上凸包:

  • 在涉及到 "凸包"问题时, 一定要避免 重复点 duplicate!!! 因为, 如果一个向量是零向量, 这是很未知的一种情况.
    即要对点 进行判重; 因为这里已经sort过了, 可以用一个is_duplicate数组来标识;
    比如是: [3 3 3] 则第一个3 保留下来, 后面的重复3 就设置为 is_duplicate

  • 对 “下凸包”, 他也是 递增的; 上凸包是: mi -> 顺时针 -> ma; 下凸包是: mi -> 逆时针 -> ma;

凸包模板

添加链接描述

sort( points.begin(), points.end());
VE_< bool> is_duplicate( n, false);
{
/// uniqueFOR_(i, 1, n-1, 1){if( points[ i].equal( points[ i-1], eps)){is_duplicate[ i] = true;}}
}VE_< int> obver( n), under( n); // size = capa = n
obver.resize( 0); // size=0, capa = n
under.resize( 0);
{/// obovePB_( obver, 0);FOR_(i, 1, n-1, 1){if( is_duplicate[ i]){continue;}if( obver.size() == 1){PB_( obver, i);}else{while( obver.size() >= 2){const auto & p_beg = points[ ATT_(obver, 1)];const auto & p_end = points[ ATT_(obver, 0)];Vector2D< double> cur( p_beg, p_end);Vector2D< double> nex( p_beg, points[ i]);if( nex.relative( cur, eps) == Direction2D_Left){ ' 顺时针 'obver.pop_back();}else{break;}}PB_( obver, i);}}
}{
/// underPB_( under, 0);FOR_(i, 1, n-1, 1){if( is_duplicate[ i]){continue;}if( under.size() == 1){PB_( under, i);}else{while( under.size() >= 2){const auto & p_beg = points[ ATT_(under, 1)];const auto & p_end = points[ ATT_(under, 0)];Vector2D< double> cur( p_beg, p_end);Vector2D< double> nex( p_beg, points[ i]);if( nex.relative( cur, eps) == Direction2D_Right){ ' 逆时针 'under.pop_back();}else{break;}}PB_( under, i);}}}
double ans = 0;
FOR_(i, 0, obver.size()-2, 1){ans += points[ AT_(obver, i)].distance_to( points[ AT_(obver, i + 1)], eps);
}
FOR_(i, 0, under.size()-2, 1){ans += points[ AT_(under, i)].distance_to( points[ AT_(under, i + 1)], eps);
}

http://chatgpt.dhexx.cn/article/SKdv12rf.shtml

相关文章

小白兔视频格式转换器下载

1、小白兔视频格式转换器 www.xxxbbbttt.com 上传你的视频&#xff08;腾讯qlv&#xff0c;爱奇艺qsv、优酷kux&#xff09;都可以。 2、点击转换按钮&#xff0c;转换好后&#xff0c;我们把转换的视频下载到电脑里&#xff0c;就可以看到视频已经是MP4格式了。

推荐一款能够将爱奇艺qsv、腾讯qlv、优酷kux完美转换成mp4的三合一全能格式转换器

爱奇艺视频、腾讯视频、优酷视频相信很多人都在使用其中的一款或者几款软件吧&#xff0c;这三大视频网站已经主导国内视频行业&#xff0c;都是购买视频版权。因此&#xff0c;为了保护视频版权&#xff0c;就将缓存视频的格式设置成专属的qsv、qlv、kux&#xff0c;这三种视频…

kux格式怎么转换成mp4?简单快速的视频转换技巧分享

现在生活压力越来越大,过完一天忙碌的工作回到家里开始煲剧是很多人的最爱。说到看视频,资源基本都被「三巨头」——腾讯视频、爱奇艺、优酷所覆盖,而有些朋友喜欢将视频下载下来看。可是却发现,下载的视频格式是kux、qsv、qlv,普通视频播放器根本打不开,这是怎么一回事呢…

怎么使用视频转换器把kux格式转换mp4

在周末或者平时闲暇的时间&#xff0c;很多人可能就是在家里看下视频吧&#xff1f;而且最好的方式&#xff0c;还是下载到本地上来观看&#xff0c;想要啥时候看就啥时候看&#xff0c;想要看哪个地方的就看哪个地方的。但是吧&#xff0c;有人发现了&#xff0c;自己下载的视…

上网成瘾改变大脑结构:语言功能受影响,让人话都说不利索

万博 发自 凹非寺量子位 | 公众号 QbitAI 经常不受控制地拿着手机或平板&#xff0c;漫无目的的刷微博&#xff0c;逛淘宝…… 如果有&#xff0c;那就需要注意了&#xff0c;这种无法自控的上网成瘾&#xff0c;是一种被叫做互联网使用障碍&#xff08;IUD&#xff09;的健康问…

数据统计分析的16个基础概念

来源&#xff1a;EasyShu 本文约11000字&#xff0c;建议阅读20分钟本文介绍了数据统计分析的16个基本概念。 一、描述统计 描述统计是通过图表或数学方法&#xff0c;对数据资料进行整理、分析&#xff0c;并对数据的分布状态、数字特征和随机变量之间关系进行估计和描述的方法…

睡眠剥夺后皮层微结构的广泛变化

大脑皮层的微观结构受到昼夜节律和睡眠剥夺的影响&#xff0c;但这些影响的确切基础尚不清楚。t1加权和t2加权磁共振图像之间的比率(T1w/T2w比率)与髓磷脂水平和树突密度有关&#xff0c;这可能为研究睡眠剥夺大脑的皮质内微观结构提供新的见解。在这里&#xff0c;我们检测了4…

常用的数据分析方法汇总

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 一、描述统计 描述统计是通过图表或数学方法&#xff0c;对数据资料进行整理、分析&#xff0c;并对数据的分布状态、数字特征和随机变量之间关系进行估计和描述的方法…

论文阅读:FLGCNN: A novel fully convolutional neural network for end-to-endmonaural speech enhancement

论文题目&#xff1a;FLGCNN: A novel fully convolutional neural network for end-to-end monaural speech enhancement with utterance-based objective functions 一种新颖的全卷积神经网络&#xff0c;用于具有基于话语的目标函数…

民安汇智量表科普!满意度调查量表怎么选?

满意度量表是进行满意度调查的主要工具和手段。目前的满意度量表因其适用的对象、范围和特点各异&#xff0c;存在着多种类型差异。每个量表都有自己的特点&#xff0c;没有一个量表能用于所有的客户满意度评价&#xff0c;哪怕是在同一期满意度调查&#xff0c;都会因地制宜&a…

一文介绍各种量表类型!

量表是一种测量工具&#xff0c;通常用来测量人们的主观态度、意见或价值观念。我们经常会在问卷中使用量表对调查对象进行测量&#xff0c;最常见到的就是李克特量表&#xff0c;关于量表还有很多的种类&#xff0c;这里具体介绍几种&#xff1a; 一. 李克特量表&#xff08;…

数据分析之数据预处理、分析建模、可视化

大纲 思维导图1. 数据分析概述1.1 简介1.2 发展历程1.3 应用领域1.4 开发流程 2. 数据类型2.1 结构化与非结构化数据2.2 定性与定量数据2.3 截面数据与时间序列数据 3. 数据来源4. 数据预处理方法4.1 数据清洗4.2 数据集成4.3 数据规约4.4 数据变换 5. 数据分析模型5.1 对比分析…

amos里CFA可行性辨别结果怎么看_论文用问卷调查法,数据分析怎么做?

论文问卷数据的分析,看起来简单,好像每个人都会做。但是做起来还真的有点难度。很多初次使用问卷调查方法的人大多以为,问卷数据分析嘛,无外乎对单选题做做频率分析,看看选择不同的选项的人占比有多少。对于评分题目,看看均值是多少,不同性别,年龄段的人群均值是多少。…

『统计学』常用的数据分析方法都在这了!Part.2

阿平 | 作者 知乎 | 来源 1 相关分析 研究现象之间是否存在某种依存关系&#xff0c;对具体有依存关系的现象探讨相关方向及相关程度。 单相关&#xff1a;两个因素之间的相关关系叫单相关&#xff0c;即研究时只涉及一个自变量和一个因变量复相关 &#xff1a;三个或三个以上因…

常用数据分析方法总结

最近优化一个画像产品&#xff0c;用到一些数据分析方法&#xff0c;这里总结一下。 主要参考&#xff1a;https://www.jianshu.com/p/809fb2261b23 &#xff0c;补充一些细节 一、描述统计 描述统计是通过图表或数学方法&#xff0c;对数据资料进行整理、分析&#xff0c;并…

阅读《Unsupervised Evaluation of Interactive Dialog with DialoGPT》

Unsupervised Evaluation of Interactive Dialog with DialoGPT 目录 Abstract 1 Introduction 2 Related Work 2.1 Automatic Dialog Evaluation 2.2 Dialog Qualities 2.3 Pre-trained Dialog Models 3 Data Collection 3.1 Turn-Level Annotation 3.2 Dialog-Level Annotati…

循证护理教育中的移动辅助同伴评估方法

摘要&#xff1a; 学习循证护理的学生可以帮助医疗保健团队做出适当的医疗决策&#xff0c;并为患者提供有价值的建议&#xff0c;从而优化特定情况下的患者护理质量。在临床工作中&#xff0c;护理人员通过搜索相关的经验性护理文献来参与决策&#xff0c;这是进入临床实践所需…

期末考试复习笔记(标红表示重要)

目录 相关系数的比较 数据的类型 回归模型的统计检验与统计意义 参数检验 非参数检验 统计距离 量表 李克特量表 权重 聚类图分析 聚类分析简介 聚类的用途 聚类方法 两步聚类法(TwoStep Cluster) 箱线图分析 中心位置的作用 伪相关 标准化的性质 受&#xf…

如何换算不同等级的李克特量表(5级、7级、10级等)

※ 版权所有&#xff0c;转载请联系作者 ※ 在做量表问卷的时候&#xff0c;会发现有些问卷是5级李克特量表&#xff08;5-point Likert scale&#xff09;&#xff0c;有的是7级李克特量表&#xff08;7-point Likert scale&#xff09;&#xff0c;有的为了更好的得到结果使…

冷门暴利副业!成本2000,一月稳赚3万

大叔最近认识一位95后女孩&#xff0c;年纪轻轻&#xff0c;生意却做得红红火火。 大叔对挣钱的事情都特别有兴趣&#xff0c;好奇打听了一下这个姑娘到底做的是哪们子生意。 这一打听真是让我大开眼界&#xff0c;对现在年轻人的赚钱思维、生意直觉&#xff0c;很是佩服。 这姑…