7凸包问题(Graham扫描法)

来源:互联网 发布:C语言中else if 编辑:程序博客网 时间:2024/05/24 06:28

凸包(百度百科):

     点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。

顶点个数n
(1)排序:
    在点集Q中找最左下方的点p0,就是x坐标和y坐标都最小的点,其余的点计算它们的极坐标幅角,以幅角的非降序顺序来排序,如果有幅角相同的,最接近p0的优先。(这是《ACM程序设计培训教程》上的排序方法,由于看不懂什么是幅角,于是上网找了另一种排序方法,效果是一样的,具体见附)
(2)扫描:
    堆栈初始化为chs(n) = {pn-1, p0},栈顶指针ps初始化为1,按排序好的点,从p1到pn-1扫描,如果pi (i=1...n-1)和chs栈顶的两个元素(chs[sp-1],chs[sp])的三角形符号是正的,说明chs[sp-1],chs[sp],pi是逆时针方向,形成的边是凸边,所以可以把pi加入栈,sp++,继续扫描后面的pi+1;如果三角形符号是负的,那chs[sp]不可能是凸包的极点,出栈,sp--,而pi仍旧是pi。下一轮仍旧是chs[sp-1],chs[sp], pi.
 
附:矢量叉积
   设有点p0(x0,y0),p1(x1,y1),p2(x2,y2).(p0p1),(p0p2)是共p0的两条向量,叉积d = (p0p1)x(p0p2) = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0)
   叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:
若 d > 0 , 则(p0p1)在(p0p2)的顺时针方向。
若 d < 0 , 则(p0p1)在(p0p2)的逆时针方向。(图示方向)
若 d = 0 , 则(p0p1)与(p0p2)共线,但可能同向也可能反向。
练习:
poj 1113 Wall
poj 2187 Beauty Contest
http://acm.pku.edu.cn/JudgeOnline/problem?id=2187
题目意思为:给你N个点,求出其中最长两点的距离的平方。
凸包 + 枚举