预备知识:凸集:集合S中任意两点的连线都在集合S中,如果简单的理解,可以理解为凸边形

凸包:对于给定集合X,所有包含X的凸集的交集,简单的理解,就是包含X的最小凸集,或者就是最外圈的点连起来

极角排序

用叉乘判断方向:向量a叉乘向量b的值就是|a| |b| sinθ,θ是向量a逆时针旋转到向量b的角度(右手定则),所以叉积是正的就是逆时针旋转过去,等于0就是共线,小于零就是逆时针旋转过去的

Graham Scan算法是一个用来求凸包的算法

第一步:把点按逆时针顺序排好

具体做法:找到左下角的点(横坐标和纵坐标都是最小的),以这个点为极点,想象有一个平行于x轴的并且和x轴正方向同向的极轴,然后进行极角排序

第二步:找凸包

具体做法:开一个栈,top=元素个数,从第0个点遍历到第n个再到第0个

对于第i个点,构造向量a(top-2->top-1),向量b(top-2->i),计算向量a 叉乘 向量b,

如果不足两个点,i入栈

如果=0,说明共线,可以i入栈

如果>0,说明是逆时针的,可以i入栈

如果是<0说明已经凹进去了,第top-1点不符合凸包的定义,top-1出栈,--top,重复执行,直到成功入栈

结合图理解就是如果连2,3的话就已经凹进去了(左上角的)

下面看一个维基的动态版本

代码

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
class point {
public:double x, y;point(const double &x = 0, const double &y = 0) :x(x), y(y) {}
};
int n;
//p是点集,convex是栈
point p[1005], convex[1005];
//叉乘
double cross(const point &a, const point &b, const point &c, const point &d) {return (b.x - a.x)*(d.y - c.y) - (b.y - a.y)*(d.x - c.x);
}
//极角排序,角度相同按x升序
bool cmp(const point &a, const point &b) {double temp = cross(p[0], a, p[0], b);if (!temp)return a.x < b.x;return temp > 0;
}
//距离
double getDistance(const point &a, const point &b) {return sqrt(1.0*(a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
//graham scan算法,返回凸包顶点个数
int graham() {int top = 0, i = 0;while (i <= n) {//不足两个直接入栈,否则叉积判断方向,直到成功入栈while (top >= 2 && cross(convex[top - 2], convex[top - 1], convex[top - 2], p[i%n]) < 0)--top;convex[top] = p[i%n];++top;++i;}return top;
}
int main() {int num = 0;scanf("%d", &n);//读入点找到左下角的点for (int i = 0; i < n; ++i) {scanf("%lf%lf", &p[i].x, &p[i].y);if (p[i].y < p[num].y || p[i].y == p[num].y&&p[i].x < p[num].x)num = i;}swap(p[0], p[num]);//极角排序sort(p + 1, p + n, cmp);num = graham();double ans = 0;//求周长for (int i = 1; i < num; ++i)ans += getDistance(convex[i], convex[i - 1]);printf("%.0lf\n", ans);return 0;
}

-----------------------

题目:

poj1113

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
class point {
public:int x, y;point(const int &x=0, const int &y=0) :x(x), y(y) {}
};
int n;
point p[1005], convex[1005];
int cross(const point &a, const point &b, const point &c, const point &d) {return (b.x - a.x)*(d.y - c.y) - (b.y - a.y)*(d.x - c.x);
}
bool cmp(const point &a, const point &b) {int temp = cross(p[0], a, p[0], b);if (!temp)return a.x < b.x;return temp > 0;
}
double getDistance(const point &a, const point &b) {return sqrt(1.0*(a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
int graham() {int top = 2, i = 2;convex[0] = p[0];convex[1] = p[1];while (i <= n) {while (top >= 2 && cross(convex[top - 2], convex[top - 1], convex[top - 2], p[i%n]) < 0)--top;convex[top] = p[i%n];++top;++i;}return top;
}
int main() {int r, num = 0;scanf("%d%d", &n, &r);for (int i = 0; i < n; ++i) {scanf("%d%d", &p[i].x, &p[i].y);if (p[i].y < p[num].y || p[i].y == p[num].y&&p[i].x < p[num].x)num = i;}swap(p[0], p[num]);sort(p + 1, p + n, cmp);num = graham();double ans = 0;for (int i = 1; i < num; ++i)ans += getDistance(convex[i], convex[i - 1]);ans += 2 * acos(-1.0)*r;printf("%.0lf\n", ans);return 0;
}

---------------------

有空补充一下快包和旋转卡壳

Graham Scan算法相关推荐

  1. 凸包Graham Scan算法实现

    凸包Graham Scan算法实现 凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对 ...

  2. graham算法 java_凸包Graham Scan算法实现

    凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理.一般算法是将共线 ...

  3. 计算几何入门 1.6:凸包的构造——Graham Scan算法

    上文简要分析出了凸包构造问题算法的下界:O(nlogn),在此就引入一种下界意义上最优的算法:Graham Scan算法.这种算法可以保证在最坏情况下时间复杂度也不超过nlogn.我们先大致了解一下算 ...

  4. 计算几何--凸包之graham scan算法

    Graham scan算法主要步骤: 找出所有已知点的y值最小,如果相同,取x值最小的点,作为基准点s. 以s为基准,所有的点按照与X轴夹角从小到大排序. 使用两个栈,一个记录已访问的点,一个记录未访 ...

  5. Graham Scan凸包算法

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

  6. Python:实现graham scan葛立恒扫描法算法(附完整源码)

    Python:实现graham scan葛立恒扫描法算法 from __future__ import annotations from collections import deque from e ...

  7. 社区发现算法——SCAN算法

    论文地址 该算法用于检测网络中的社区.桥节点和离群点.它基于结构相似性度量对顶点进行聚类.该算法特点是:速度快,效率高,每个顶点只访问一次. 主要贡献是能够识别出桥节点和离群点两种特殊点. 前面提到的 ...

  8. 操作系统 磁头引臂调度 SCAN算法 JAVA实现(二)

    操作系统--磁头引臂调度SCAN算法 JAVA实现--双磁头引臂 具体要求 代码~ 说明 重要说明 具体要求 代码~ package com.guangluo.OS;import java.util. ...

  9. SCAN算法 | 磁头引臂调度问题 | 双磁头进阶 | Java实现(详细注释)

    写在前面 欢迎讨论. 问题描述 用JAVA同步方法实现磁头引臂调度问题,采用SCAN算法. 要求:(1) 给出核心调度解法,用JAVA类实现,其中包含require(dest)和release()两个 ...

最新文章

  1. EasyUI--datebox设置默认时间
  2. 傅里叶变换时间复杂度
  3. AR、美颜、机器人:计算机视觉库几乎无所不在
  4. NYOJ 485 A*B Problem
  5. Oracle中Cursor介绍
  6. WebRTC视频数据流程分析
  7. 在Word XP中也能插入国际音标、拼音
  8. Tensorflow学习笔记4:分布式Tensorflow
  9. 字体模糊的解决办法 Windows Mobile
  10. 谈论为什么要写博客的重要性
  11. 解决VMware 小度wifi 驱动报错问题 Driver error
  12. gini指数与cart 决策树
  13. 如何设置vs2005的环境变量
  14. 基于角色的权限管理系统设计思路
  15. getinfo()java,Java Provider getInfo()用法及代碼示例
  16. css动漫效果库,10 个最佳 CSS 动画库
  17. matlab相机标定工具箱讲解,matlab 相机标定工具箱
  18. SLT容器使用技巧以及注意事项
  19. 大数据时代网络舆情与社会治理研究
  20. linux socket write()函数阻塞卡住线程问题(线程无法结束)write()非阻塞代码

热门文章

  1. 安装文本编辑器 Geany
  2. MAC 安装windows
  3. xtend怎么使用_Java替代Xtend又推出了另一个块摇摆更新
  4. 设计模式03 行为型模式
  5. 飞机的各参数指标matlab,通达信飞机起飞及选股指标公式
  6. 内存换CPU CPU换内存例子
  7. 元宇宙NFT最近最火的项目,该如何选择平台呢
  8. 苹果手机通话没有声音是怎么回事_手机通话声音太小?只需要打开这个开关,声音变大好几倍...
  9. Modelarts培训第一次
  10. 阿里实现Redis亿级存储的方案