Graham算法构造凸包

double eps = 1e-10;

struct P
{
    double x, y;
    P(double x=0, double y=0):x(x), y(y) {}
    double add(double a, double b){
        if(abs(a+b)<eps*(abs(a)+abs(b))) return 0;
        return a+b;
    }
    P operator + (P p){
        return P(add(x, p.x), add(y, p.y));
    }
    P operator - (P p){
        return P(add(x, -p.x), add(y, -p.y));
    }
    P operator *(double d){
        return P(x*d, y*d);
    }
    double dot(P p){                 //点积
        return add(x*p.x, y*p.y);
    }
    double det(P p){                 //差积
        return add(x*p.y, -y*p.x);
    }
}ps[10000 + 100];

double dist(P a, P b)
{
    return sqrt((b-a).dot(b-a));
}

bool cmp_x(const P& p, const P& q)
{
    if(p.x!=q.x) return p.x < q.x;
    return p.y < q.y;
}

vector<P> convex_hull(P *ps, int n)
{
    sort(ps, ps+n, cmp_x);
    int k = 0;          //凸包顶点数
    vector<P> qs(n*2);
    //构造凸包的下侧
    for(int i=0; i<n; i++)
    {
        while(k>1 && (qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) k--;
        qs[k++] = ps[i];
    }
    //构造凸包的上侧
    for(int i=n-2,t=k; i>=0; i--)
    {
        while(k>t && (qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) k--;
        qs[k++] = ps[i];
    }
    qs.resize(k-1);
    return qs;
}
时间: 2024-12-08 09:11:03

Graham算法构造凸包的相关文章

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

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

poj2187 求平面最远点对,garham_scan算法求凸包

poj2187 求平面最远点对,garham_scan算法求凸包 Beauty Contest Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 29666   Accepted: 9180 Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'M

HDU 4946 Area of Mushroom(构造凸包)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4946 题目大意:在一个平面上有n个点p1,p2,p3,p4....pn,每个点可以以v的速度在平面上移动,对于平面上任意一点,假设有唯一一个点pi从初始的位置到这个点的时间最短,那么就说平面上的这个点是属于pi这点管辖的.现在要你判断pi管辖的范围是不是无穷大的,如果是输出1,否则输出0: 首先大致的方法就是构造凸包,不过要遵循一下前提: 一定是只考虑速度最大的点,然后,如果两个点所在的位置与速度都

c/c++ 用普利姆(prim)算法构造最小生成树

c/c++ 用普利姆(prim)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: ? 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路.这时,自然会考虑,如何在最节省经费的前提下建立这个公路网络. ? 每2个城市之间都可以设置一条公路,相应地都要付出一定的经济代价.n个城市之间,最多可以设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少? 普利姆(prim)算法的大致思路: ? 大致思想是:设图G顶点

c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树

c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路.这时,自然会考虑,如何在最节省经费的前提下建立这个公路网络. 每2个城市之间都可以设置一条公路,相应地都要付出一定的经济代价.n个城市之间,最多可以设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少? 克鲁斯卡尔(kruskal)算法的大致思路: 把每条边的权重

(模板)poj1113(graham扫描法求凸包)

题目链接:https://vjudge.net/problem/POJ-1113 题意:简化下题意即求凸包的周长+2×PI×r. 思路:用graham求凸包,模板是kuangbin的. AC code: #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn=1005; const double PI=

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 算法

三点以下的情况就不写了 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