凸包与Andrew算法——学习笔记
来源:互联网 发布:java 小写字母转大写 编辑:程序博客网 时间:2024/06/13 05:23
凸包
已知一个点集,凸包就是指将这些些点全部包围在内部的,且面积最小的凸多边形。
举个例子
以下介绍一种解决凸包问题的算法Andrew算法。
Andrew算法
首先先把所有点排序(排序方法同前面定义<相同),必要时删除重复点,然后把点1和点2放入凸包的栈中,然后从p3开始当新的点在凸包前进的方向的左边时加入并继续,否则说明方向已经向内凹了,此时依次删除当时在栈顶的点,直至新点在左边。
依旧举栗子:
此时新点E方向在向量CD的右边,所以需要在凸包的栈中删除C和D,让B的下一个点为E,重复此过程,直至碰到最右边的pn,求出了凸包下部分,然后反过来求出凸包的上部分,合起来求得完整的凸包。
Andrew算法复杂度并不高,排序后处理就是线性的O(n),加上排序也只是O(nlogn)。
代码:
void Andrew(){ sort(a+1,a+n+1); tot=0; for (int i=1;i<=n;i++) { while (tot>1&&dcmp(cross(b[tot]-b[tot-1],a[i]-b[tot-1]))<0) tot--; b[++tot]=a[i]; } int k=tot; for (int i=n-1;i>0;i--) { while (tot>k&&dcmp(cross(b[tot]-b[tot-1],a[i]-b[tot-1]))<0) tot--; b[++tot]=a[i]; } if (n>1) tot--;//由于第一个点会算两遍,所以最终凸包点个数要-1,但有一些求凸包周长的时候为了计算方便去掉这一行。}
模板:POJ 1113 说是凸包的边长加2*pi*r(r已给出),然而菜鸡fhj不会证明,若各位大佬知道请务必在评论区教教本菜鸡。
#include<cmath>#include<cstdio>#include<algorithm>using namespace std;int n,tot;double ans,R,eps=1e-5;struct data{ double x,y; data (double x=0,double y=0):x(x),y(y){} bool operator < (const data b) const{ return (x<b.x||(x==b.x&&y<b.y)); }}a[1005],b[1005];data operator - (const data a,const data b){return data(a.x-b.x,a.y-b.y);}double dot(const data a,const data b){return a.x*b.x+a.y*b.y;}double leng(const data x){return sqrt(dot(x,x));}double cross(const data a,const data b){return a.x*b.y-a.y*b.x;}int dcmp(double x){ if (fabs(x)<eps) return 0; return (x<0)?-1:1;}void Andrew(){ sort(a+1,a+n+1); tot=0; for (int i=1;i<=n;i++) { while (tot>1&&dcmp(cross(b[tot]-b[tot-1],a[i]-b[tot-1]))<0) tot--; b[++tot]=a[i]; } int k=tot; for (int i=n-1;i>0;i--) { while (tot>k&&dcmp(cross(b[tot]-b[tot-1],a[i]-b[tot-1]))<0) tot--; b[++tot]=a[i]; }}int main(){ freopen("wall.in","r",stdin); freopen("wall.out","w",stdout); scanf("%d%lf",&n,&R); for (int i=1;i<=n;i++) { double x,y; scanf("%lf%lf",&x,&y); a[i]=data(x,y); } Andrew(); ans=0.0; for (int i=1;i<tot;i++) ans+=leng(b[i+1]-b[i]); printf("%0.0lf",ans+2*R*3.14159); return 0;}
PS:本博客比较简陋,加之作者fhj水平实在菜鸡,所以各位大佬请多多谅解,如有错误,请多多指出!
PPS:Orz zzk
阅读全文
0 0
- 凸包与Andrew算法——学习笔记
- 凸包——Andrew(安德鲁)算法
- 凸包——Andrew算法
- 凸包之Andrew算法——模板整理
- 二维凸包 Andrew算法
- Andrew Ng机器学习笔记(五)——生成学习算法和朴素贝叶斯算法
- 监督学习之生成学习算法——Andrew Ng机器学习笔记(四)
- 【凸包模板】Graham算法、Andrew算法
- 机器学习笔记(Andrew Ng)——非参数学习算法(non-parametric algorithm)
- Andrew Ng机器学习笔记(三)——牛顿算法
- 计算几何--凸包--Andrew算法--HDU1392
- 1214:凸包模板(Andrew算法)
- 浅谈凸包之Andrew 与 Graham
- 机器学习——Andrew NG老师课程学习笔记
- Andrew Ng机器学习笔记+Weka相关算法实现(一)梯度下降与回归方法
- Coursera机器学习(Andrew Ng)笔记:ML算法指导与系统设计
- 非监督学习之k-means聚类算法——Andrew Ng机器学习笔记(九)
- 非监督学习之混合高斯模型和EM算法——Andrew Ng机器学习笔记(十)
- nmon监控工具的使用
- Java服务端时区的几点思考
- Android7.0中文文档(API)-- AutoCompleteTextView.Validator
- c# 判断字符串空值的方法
- 符号匹配问题
- 凸包与Andrew算法——学习笔记
- OBS Classic经典版已经不再支持
- 一分钟了解“Matlab中ismember函数的用法”
- 子进程的异步等待方式
- tomcat集群同步原理
- python __str__,__repr__,__call__()
- PAT乙级真题及训练集(5)--1046. 划拳(15)
- java的模板方法设计模式
- SQLite/sharePreference可视化工具