凸包 Graham 算法

import math

class Point( object ):

    def __init__( self, x, y ):
        self.x = x
        self.y = y

    def __cmp__( self, other ):
        if self.y < other.y:
            return -1
        elif self.y == other.y:
            if self.x < other.x:
                return -1
            elif self.x == other.x:
                return 0
            else:
                return 1
        else:
            return 1

    def __repr__( self ):
        return "(X: {x}, Y:{y})".format( x = self.x, y = self.y )

    @staticmethod
    def distance( p1, p2 ):
        return math.sqrt( ( p1.x - p2.x ) * ( p1.x - p2.x ) +                           ( p1.y - p2.y ) * ( p1.y - p2.y ) )

    @staticmethod
    def crossMultiply( p1, p2, p3 ):
        return ( p2.x - p1.x ) * ( p3.y - p1.y ) -                ( p2.y - p1.y ) * ( p3.x - p1.x )

points  = []
results = []

def graham():

    def find_start_point():
        res = Point( float( 'inf' ), float( 'inf' ) )
        for p in points:
            if res > p:
                res = p
        return res

    def _cmp( p1, p2 ):
        m = Point.crossMultiply( start_point, p1, p2 )
        if m < 0:
            return 1
        elif m == 0 and              Point.distance( start_point, p1 ) < Point.distance( start_point, p2 ):
            return 1
        else:
            return -1

    global points, results

    start_point = find_start_point()
    points.remove( start_point )
    points = sorted( points, _cmp )
    results.extend( [start_point, points.pop( 0 ), points.pop( 0 )] )

    for p in points:
        while ( Point.crossMultiply( results[-2], results[-1], p ) ) <= 0:
            results.pop()
        results.append( p )

    return results

if __name__ == "__main__":

    points.extend( [ Point( 30, 30 ),
                     Point( 50, 60 ),
                     Point( 60, 20 ),
                     Point( 70, 45 ),
                     Point( 86, 39 ),
                     Point( 112, 60 ),
                     Point( 200, 113 ),
                     Point( 250, 50 ),
                     Point( 300, 200 ),
                     Point( 130, 240 ),
                     Point( 76, 150 ),
                     Point( 47, 76 ),
                     Point( 36, 40 ),
                     Point( 33, 35 ) ] )
    res = graham()
    print res
时间: 2024-07-29 16:39:51

凸包 Graham 算法的相关文章

二维凸包 Graham 算法

三点以下的情况就不写了 Python: import math class Point( object ): def __init__( self, x, y ): self.x = x self.y = y def __cmp__( self, other ): if self.y < other.y: return -1 elif self.y == other.y: if self.x < other.x: return -1 elif self.x == other.x: return

【POJ 2187】 Beauty Contest (凸包-Graham扫描算法)

[POJ 2187] Beauty Contest (凸包-Graham扫描算法) 找平面最远点对 数据很大 用暴力会T..我感觉-- 扫描出个凸包 然后枚举凸包上的点即可 没坑 int也可过 注意重边跟共线就行 代码下附赠几组数据 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include

Graham算法—二维点集VC++实现

一.凸包定义 通俗的说就是:一组平面上的点,求一个包含所有点的最小凸多边形,这个最小凸多边形就是凸包. 二.Graham算法思想 概要:Graham算法的主要思想就是,最终形成的凸包,即包围所有点的凸多边形,假定多边形是按逆时针方向生成的,那么多边形内部包围的所有点与多边形每个有向边的关系都是:点在有向边的左边.依照此思想,只要找到一个出发点,然后依此出发点按逆时针方向构建多边形,并保证每加入一条有向边时,都要满足其余点都在该边的左边. ***点与线的关系定义:平面上的三点P1(x1,y1),P

求凸包—— graham_scan算法

求凸包—— graham_scan算法 先按Y-X排序,在按对p0的极角排序,然后进行扫描 Point stk[maxn]; int top; bool cmpYX(const Point A,const Point B)//按Y-X排序 { if(A.y<B.y) return true; if(A.y==B.y){ return A.x<=B.x; } return false; } bool cmp(const Point A,const Point B)//按极角排序 { return

HDU 5928 DP 凸包graham

给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也就是 dp[j][k]代表当前链末端为j,其内部点包括边界数量为k的最小长度.这样最后得到的一定是最优的凸包. 然后就是要注意要dp[j][k]的值不能超过L,每跑一次凸包,求个最大的点数量就好了. 和DP结合的计算几何题,主要考虑DP怎么搞 /** @Date : 2017-09-27 17:27

[hdu contest 2019-07-29] Azshara&#39;s deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点. 首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里. 然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp. 区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连

Graham算法模板

Graham算法模板 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 typedef long long ll; 8 const int maxn=1100; 9 const double pi=acos(-1.0); 10 struct

Graham算法求平面散点集的凸包

本文参考自<<算法导论>>章节33.3 寻找凸包 完整VS2010工程见:http://download.csdn.net/detail/tangxin19930330/9406625 算法主要利用向量的叉积判断点和线段的位置关系,详见 向量叉积,然后从左下角点按逆时针方向寻找最边缘的线段,利用的原理就是从凸包上任意一点逆时针出发,每到一个节点,一定会向左拐.算法复杂度为O(nlg(n)) 算法主要实现如下: 1 // 输入:点数组arrInPt,个数nInPtCount,包含所有

凸包——Graham扫描法和Andrew算法

凸包:能围住所有给出的点的面积最小的多边形(个人理解) Graham:选取y值最小的点,将其它点极角排序,依次把1~n号点加入栈中,判断当前点.栈顶.栈顶下面那个点三者的关系(嘻嘻),一直这样做就好了 判断用叉积,也就是如下图的要判掉(top--) 其实上图是不对的哦,你有没有反应过来呢~按极角排序后不会有这种情况哦,肯定是先连a[i],再连s[top]的 具体实现看代码吧~ #include<cstdio> #include<cmath> #include<algorith