计算几何 二维凸包问题 Andrew算法
凸包:把给定点包围在内部的、面积最小的凸多边形。
Andrew算法是Graham算法的变种,速度更快稳定性也更好。
首先把全部点排序。依照第一keywordx第二keywordy从小到大排序,删除反复点后得到点序列P1...Pn。
1)把P1,P2放入凸包中,凸包中的点使用栈存储
2)从p3開始,当下一个点在凸包当前前进方向(即直线p1p2)左边的时候继续;
3)否则依次删除近期增加凸包的点,直到新点在左边。
如图,新点P18在当前前进方向P10P15的右边(使用叉积推断),因此须要从凸包上删除点P15和P10。让P8的下一个点为P18。反复该过程直到碰到最右边的Pn,求出下凸包即凸包的下轮廓。然后从Pn反过来反复该步骤求出上凸包,合并起来后就是完整的凸包。
该算法扫描为O(n)复杂度,排序O(nlogn)。
C++ code(刘汝佳《算法竞赛入门经典-训练指南》模板)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath> using namespace std; const double eps = 1e-8,Pi=3.14159265; int n; inline int dcmp(double x)//三态函数
{
if(fabs(x) < eps) return 0;
else return x>0 ? 1 : -1;
} #define Vector Point
struct Point
{
double x,y;
inline Point(double x=0,double y=0):x(x),y(y) {}
}p[10000+5],ch[10000+5]; bool myCmp(Point A, Point B)
{
if(A.x != B.x) return A.x < B.x;
else return A.y < B.y;
} Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator - (Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);}
bool operator == (const Vector& A, const Vector& B) {return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;} inline double Cross(Vector A, Vector B)//叉积
{
return A.x * B.y - A.y * B.x;
} int ConvexHull()
{
sort(p,p+n,myCmp);
int m = 0;
for(int i = 0; i <n; i++)
{
while(m > 1 && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--)
{
while(m > k && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
return m;
} double Dis(Point A, Point B)
{
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
} int main()
{
int m;
cin>>n;
for(int i = 0; i < n; i++)
{
int a,b;
cin>>a>>b;
p[i] = Point(a,b);
}
m = ConvexHull();
//计算凸包周长
double ans=0.0;
for(int i = 0; i < m-1; i++)
ans += Dis(ch[i],ch[i+1]);
ans += Dis(ch[m-1],ch[0]);
printf("%.1f",ans);
}
例题:
wikioi1298(click me)
求解二维凸包并计算周长
wikioi3201(click me)
求解二维凸包并计算周长
poj1113( id=1113">click me
本题翻译:http://blog.csdn.net/lytning/article/details/24046075
求解二维凸包并增加一个圆的周长
计算几何 二维凸包问题 Andrew算法的更多相关文章
- 二维凸包 Graham扫描算法
题目链接: http://poj.org/problem?id=1113 求下列点的凸包 求得凸包如下: Graham扫描算法: 找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小 ...
- Andrew算法求二维凸包-学习笔记
凸包的概念 首先,引入凸包的概念: (有点窄的时候...图片右边可能会被吞,拉开图片看就可以了) 大概长这个样子: 那么,给定一些散点,如何快速地求出凸包呢(用在凸包上的点来表示凸包) Andrew算 ...
- 【计算几何】二维凸包——Graham's Scan法
凸包 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内.右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包. 一组平面上的点, ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- UVA 10652 Board Wrapping(二维凸包)
传送门 刘汝佳<算法竞赛入门经典>P272例题6包装木板 题意:有n块矩形木板,你的任务是用一个面积尽量小的凸多边形把它们抱起来,并计算出木板占整个包装面积的百分比. 输入:t组数据,每组 ...
- 使用Graham扫描法求二维凸包的一个程序
#include <iostream> #include <cstring> #include <cstdlib> #include <cmath> # ...
- luogu P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows
题解: 二维凸包裸题 按照x坐标为第一关键字,y坐标为第二关键字排序 然后相邻判断叉积用单调队列搞过去 正反都做一次就好了 代码: #include <bits/stdc++.h> usi ...
- 【洛谷 P2742】【模板】二维凸包
题目链接 二维凸包板子..有时间会补总结的. #include <cstdio> #include <cmath> #include <algorithm> usi ...
- poj 2079 Triangle (二维凸包旋转卡壳)
Triangle Time Limit: 3000MS Memory Limit: 30000KB 64bit IO Format: %I64d & %I64u Submit Stat ...
随机推荐
- printf的字符型
参 数 说 明 %s 按实际宽度输出一个字符串 %ms m指定宽度(不足时左补空格,大于时按实际宽度输出) %-ms 左对齐,不足时右补空格 %m.ns 输出占m个字符位置,其中字符数最多n个,左 ...
- zoj3675 BFS+状态压缩
#include <stdio.h> #include <string.h> #include <queue> using namespace std; int n ...
- 【转】Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内容包括::1 fail-fast简介2 fail-fast示例 ...
- js技巧(二)
1.封装获取id: function show(Id){ var aa=document.getElementById(Id); return aa; } 调用:console.log(show(&q ...
- html中设置浏览器解码方式
通过添加一行标签: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"& ...
- 基于openstack平台的几种Cloud DB解决方案
方案一.openstack 官方 trove解决方案 此方案进行过镜像的打包,由于网络问题,还未能成功实现 方案二.salt 或者ansible+ docker 由于 docker部署数据库,在数据库 ...
- 如何在Linuxt系统下运行maven项目
如何在Linuxt系统下运行maven项目 我们知道现在利用MAVEN来管理JAVA项目是非常常见的.比如公司一般都有一个自己的MAVEN仓库,通过MAVEN仓库来解决我们的项目依赖,更加方便的构建项 ...
- CNN-CV识别简史2012-2017:从 AlexNet、ResNet 到 Mask RCNN
原文:计算机视觉识别简史:从 AlexNet.ResNet 到 Mask RCNN 总是找不到原文,标记一下. 一切从这里开始:现代物体识别随着ConvNets的发展而发展,这一切始于2 ...
- day07-列表类型/元组类型/字典类型/集合类型内置方法
目录 列表类型内置方法 元组类型内置方法 字典类型内置方法 集合类型内置方法 列表类型内置方法 用来存多个元素,[]内用逗号隔开任意数据类型的元素 1. list()强制类型转换 print(list ...
- 【Android】进程间通信IPC——Binder
Binder是Android中的跨进程通信方式,bindService的时候,服务端返回Binder对象,通过该对象客户端可以从服务端获取数据.在进程间通信IPC——AIDL中创建了ICustomAi ...