graham扫描法求凸包
来源:互联网 发布:网络机顶盒H3芯片 编辑:程序博客网 时间:2024/06/08 18:14
凸包的概念:
凸包(Convex Hull)是一个计算几何(图形学)中的概念。
在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。
X的凸包可以用X内所有点(X1,…Xn)的线性组合来构造.
在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。
上图中由红色线段表示的多边形就是点集Q={p0,p1,…p12}的凸包。
基本过程:
1.找到最下面的一个点,如果存在纵坐标相同,取最左面的点。取这个点作为原点。
2.把p0同点集中其他各点用线段连接,并计算这些线段与水平线的夹角,然后按夹角从小到大排序(夹角范围为 [0, 180)度),如果存在夹角相同的点,取最远点其余点直接删除。
3.创建一个栈,将p0,p1,p2三点放入栈中,之后依次遍历p3~pn各点,若栈顶的两个点和当前的点pi这三点连线的方向向顺时针方向偏转,表明栈顶的点是一个凹陷处,应删除,则栈顶元素出栈。并将pi压入栈中。如果向逆时针方向偏转,则直接压入栈中。
4.重复上述过程,直到遍历完成,在栈中的点就是凸包上的顶点。(结果图是最上边的图)
代码实现
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>#include <string>#include <stack>#define PI acos(-1.0)#define MAXN 1010using namespace std;struct point{ double x,y; double len;}s[MAXN],pt[MAXN],Point_A; // s中保存最终结果 ,pt起始点 ,Point_A左下起始点int NUM; // 凸包上总点数double Cross(point a,point b,point c) //求叉积我(ab,ac){ return (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);}double dis(point a,point b) // 求两点间的距离{ return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));}void Find(int n) //查找起始点,左下{ int temp = 0; point a = pt[0]; for(int i=0;i<n;i++){ if(pt[i].y < a.y || pt[i].y == a.y && pt[i].x < a.x){ a = pt[i]; temp = i; } } pt[temp] = pt[0]; pt[0] = a; Point_A = a; // 保存起始点}bool cmp (point a,point b) // 极角排序{ double x = Cross(Point_A,a,b); if(x > 0) return true; else if(x < 0) return false; a.len = dis(Point_A,a); b.len = dis(Point_A,b); return a.len < b.len;}int Graham(int n) //扫描法求解凸包{ int top = 2; s[0] = pt[0]; s[1] = pt[1]; s[2] = pt[2]; pt[n] = pt[0]; for(int i=3;i<=n;i++){ while(Cross(s[top-1],s[top],pt[i]) <= 0 && top > 1) top--; s[++top] = pt[i]; } return top; //表示凸包中的点数}int init(int n) // 排序,求凸包{ Find(n); sort(pt,pt+n,cmp); NUM = Graham(n);}int Perimeter() // 求凸包周长{ double sum = 0; for(int i=1;i<NUM;i++){ sum += dis(s[i-1],s[i]); } sum += dis(s[NUM-1],s[0]); return sum;}double Area() //计算面积{ double sum = 0; for(int i=1;i<NUM-1;i++){ sum += Cross(s[0],s[i],s[i+1]); } sum = fabs(sum)/2; return sum;}int main(){ int T,n,m,l,i,j; double sum,sum1,sum2; cin >> T; while(T--){ scanf("%d%d",&n,&l); for(i=0;i<n;i++){ scanf("%lf%lf",&pt[i].x,&pt[i].y); } init(n); sum = 0; sum2 = Perimeter(); sum1 = Area(); printf("%d %d\n",sum1,sum2); } return 0;}
0 0
- Graham 扫描法求凸包
- graham扫描法求凸包
- poj 1113 Wall(Graham扫描法求凸包)
- Graham扫描法
- Graham扫描算法(Graham Scan Algorithm)
- 凸包graham扫描法
- 二维求凸包 graham扫描法
- 凸包 Graham扫描法
- 凸包 graham旋转扫描
- 凸包--Graham扫描法
- 7凸包问题(Graham扫描法)
- 凸包问题的Graham扫描法
- 凸包问题(Graham扫描法)
- 寻找凸包的graham 扫描法
- poj1113Wall 求凸包周长 Graham扫描法
- 寻找凸包-graham扫描法
- 二维凸包模板 【Graham扫描算法】
- 凸包Graham扫描法->HDU3847
- PHP学习(二)--变量
- java.lang.IllegalStateException: you have not supplyed the global app context info from SDKInitializ
- spoj -705 New Distinct Substrings--后缀数组
- 鸟哥的linux私房菜中推荐的linux学习网站
- OpenGL 多重纹理
- graham扫描法求凸包
- 集群、分布式、负载均衡区别与联系
- 【Android基础】-Activity启动模式详解
- 技术角度wordpress结构优缺点分析
- netty学习(四)----伪异步IO的弊端
- POJ 3414 Pots
- [Android界面] 导航栏下划线出现偏移
- Leetcode: H-Index II
- leetcode: (235) Lowest Common Ancestor of a Binary Search Tree