LeetCode的第587题安装栅栏刚开始做的时候不知道该从哪里下手,思考一段时间无果后就去评论区找思路,在评论得知这是一道经典的凸包算法题,于是去学习了一下凸包算法。

目录

什么是凸包算法

首先来了解一下凸包

Jarvis凸包算法

向量叉积

叉积的几何意义

​附:算法题及解法

题目

题解代码


什么是凸包算法

首先来了解一下凸包

凸包(Convex Hull)是一个计算几何(图形学)中的概念。

在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的凸组合来构造.

在二维中,凸包可想象为一条刚好包著所有点的橡皮圈。

用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

常见的凸包算法有很多种,暂时只学习了Jarvis算法

Jarvis凸包算法

Jarvis 算法背后的想法非常简单。首先必须要从凸包上的某一点开始,比如从给定点集中最左边的点开始,例如最左的一点A1 。然后选择 A2点使得所有点都在向量 A1A2的左方或者右方,我们每次选择左方,需要比较所有点以 A1为原点的极坐标角度。然后以A2为原点,重复这个步骤,依次找到A3,A4,…,Ak。给定原点 p,如何找到点 q,满足其余的点 r 均在向量 pq的左边,我们使用「向量叉积」来进行判别。我们可以知道两个向量 pq, qr的叉积大于 0 时,则两个向量之间的夹角小于 180°,两个向量之间构成的旋转方向为逆时针,此时可以知道 r一定在 pq的左边;叉积等于 0时,则表示两个向量之间平行,p,q,r 在同一条直线上;叉积小于 0 时,则表示两个向量之间的夹角大于 180°,两个向量之间构成的旋转方向为顺时针,此时可以知道 r 一定在pq的右边。为了找到点 q,我们使用函数 cross() ,这个函数有 3 个参数,分别是当前凸包上的点 p,下一个会加到凸包里的点 q,其他点空间内的任何一个点 r,通过计算向量pq, qr的叉积来判断旋转方向,如果剩余所有的点 r均满足在向量 pq的左边,则此时我们将q加入凸包中。
下图说明了这样的关系,点 r 在向量pq 的左边。

cross(p,q,r)===

向量叉积

向量积,数学中又称外积、叉积,物理中称矢积、叉乘,是一种在向量空间中向量的二元运算。与点积不同,它的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量和垂直。

在二维空间中,向量A=<a1,a2>,B=<b1,b2>

叉积的几何意义

附:算法题及解法

题目

在一个二维的花园中,有一些用 (x, y) 坐标表示的树。由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树。只有当所有的树都被绳子包围时,花园才能围好栅栏。你需要找到正好位于栅栏边界上的树的坐标。

题解代码

int cross(const int* p, const int* q, const int* r) {return (q[0] - p[0]) * (r[1] - q[1]) - (q[1] - p[1]) * (r[0] - q[0]);
}
int** outerTrees(int** trees, int treesSize, int* treesColSize, int* returnSize, int** returnColumnSize) {if (treesSize < 4) {*returnSize = treesSize;*returnColumnSize = (int*)malloc(sizeof(int)*treesSize);for (int i = 0;i < treesSize;i++) {(*returnColumnSize)[i] = 2;}return trees;}int** res = (int**)malloc(sizeof(int*) * treesSize);int pos = 0;int leftMax = 0;for (int i = 0;i < treesSize;i++) {if (trees[i][0] < trees[leftMax][0]) {leftMax = i;}}bool* visited = (bool*)malloc(sizeof(bool) * treesSize);memset(visited, 0, sizeof(bool)*treesSize);int p = leftMax;do {int q = (p + 1) % treesSize;for (int r = 0;r < treesSize;r++) {if (cross(trees[p], trees[q], trees[r])<0) {q = r;}}for (int i = 0;i < treesSize;i++) {if (visited[i] || p == i || q == i) {continue;}if (cross(trees[p], trees[q], trees[i])==0) {res[pos] = (int*)malloc(sizeof(int) * 2);res[pos][0] = trees[i][0];res[pos][1] = trees[i][1];pos++;visited[i] = true;}}if (!visited[q]) {visited[q] = true;res[pos] = (int*)malloc(sizeof(int) * 2);res[pos][0] = trees[q][0];res[pos][1] = trees[q][1];pos++;}p = q;} while (p!=leftMax);*returnSize = pos;*returnColumnSize = (int*)malloc(sizeof(int) * pos);for (int i = 0;i < pos;i++) {(*returnColumnSize)[i] = 2;}free(visited);return res;
}

关于凸包算法和叉积的应用相关推荐

  1. c语言凸包算法,基于C语言的凸包算法实现

    基于C语言的凸包算法实现 非计算机专业,代码有些的不好的地方,大佬轻喷^ _ ^ 根据要求,需要使用C语言实现凸包算法--Graham扫描法,本文将从算法理解.实现思路.遇到的问题及其解决方案三个方面 ...

  2. Graham Scan凸包算法

    获得凸包的算法可以算是计算几何中最基础的算法之一了.寻找凸包的算法有很多种,Graham Scan算法是一种十分简单高效的二维凸包算法,能够在O(nlogn)的时间内找到凸包. 首先介绍一下二维向量的 ...

  3. 凸包算法Graham扫描法

    凸包算法(Graham扫描法) 转载自 SZUhg https://www.cnblogs.com/wpbing/p/9456240.html 叉乘与线段相交 判断一个点是否在一条线段的左边还是右边, ...

  4. LeetCode 587. 安装栅栏【凸包算法】【C++】【很多坑】

    凸包算法不难理解,写代码的时候主要是几何上的判定条件很容易写错. 算法的总体思想是: 1.给所有的点排序,找出极点(纵坐标最小的点,如果纵坐标一样,取横坐标最小的点) 2.除了极点之外,所有其他的点排 ...

  5. 凸包算法理解——基于MATLAB代码

    个人有个习惯:学习一个算法,要有代码能单步逐行理解. 正好这两天研究了一下凸包算法.留个记录文档吧. 代码如下,有详细备注. % 凸包算法理解   clear all;close all;clc; % ...

  6. 凸包计算几何matlab,计算几何-凸包算法 Python实现与Matlab动画演示

    凸包算法是计算几何中的最经典问题之一了.给定一个点集,计算其凸包.凸包是什么就不罗嗦了 本文给出了<计算几何--算法与应用>中一书所列凸包算法的Python实现和Matlab实现,并给出了 ...

  7. 点集凸包算法python实现(二)

    算法逻辑 在点集凸包算法python实现这篇博客中介绍了一种凸包算法,这种算法中凸包点搜索的过程较为麻烦,主要是因为计算点集连线与X轴的夹角需要考虑到四个不同象限,在这里通过计算向量夹角的方式,对凸包 ...

  8. 求多边形凸包(线性算法)--陈氏凸包算法--

    http://blog.sina.com.cn/s/blog_616e189f0100qc0u.html 陈氏凸包算法-算法参考:Computing the convex hull of a simp ...

  9. java 凸包算法_Melkman凸包算法的Java实现

    public class Point{ private float x; //X坐标 private float y; //Y坐标 private double arCos;//与P0点的角度 pub ...

  10. 多边形快速凸包算法(Melkman‘s Algorithm)

    前言 平面点集的凸包算法一文介绍了如何计算平面点集或者任意多边形的凸包.对于随机的平面点集,Graham scan和Andraw's 单调链算法已经是最快的算法了.但是对于没有自相交的封闭的简单多边形 ...

最新文章

  1. ctf 文件头crc错误_[CTF隐写]png中CRC检验错误的分析
  2. 第11章 PADS功能使用技巧(2)-最全面
  3. python装饰器类-python_类装饰器
  4. Django 的模板语法之过滤器
  5. 【二分】Distinct
  6. Java 200+ 面试题补充② Netty 模块
  7. VS2010下配置OpenCV2.2
  8. 从头开发一个Flutter插件(一)开发流程
  9. 微信公众平台开发接口返回码说明
  10. sql安装过程中,为 SQL Server 代理服务提供的凭据无效。若要继续操作,请为 SQL
  11. c语言生日快乐音乐程序,89S51演奏生日快乐的歌曲c程序
  12. 20190608 JavaBean转jsonString时首字母大写的问题
  13. Loss——Focal Loss
  14. 三国皇帝的寡妇秘史(1)
  15. Matlab绘制多个折线图的方法
  16. 为何国外的人都爱用电子邮箱?注册电子邮箱有哪些好处呢?
  17. 怎样在excel中通过出生日期计算年龄
  18. dx.jar bad class file magic (cafebabe) or version (0034.0000)
  19. oracle提示 ORA-12154: TNS: 无法解析指定的连接标识符 OCIEnvCreate 失败, 返回代码为-1,但错误消息文本不可用...
  20. 电磁兼容stm32芯片引脚失效问题

热门文章

  1. php 添加数据sql语句,PHP添加/修改/删除SQL语句
  2. Keil5手动添加Device
  3. 写的将skb copy/clone后转发到源地址的一段代码
  4. mysql 主从同步 错误_MySQL 主从同步错误(error)解决
  5. oracle单引号和双引号的区别
  6. MySQL日期时间函数总结
  7. 舆情监测软件TOOM
  8. matlab解决高等数学和线性代数的部分问题
  9. HTML资源嗅探,scrapy-2 嗅探网站,解析HTML
  10. 历史 微信开发者工具_微信开发者工具代码管理