凸包真是一个神奇的算法。。


概念

  • 凸包,我理解为凸多边形
  • 叉积 对于向量AB和向量BC,记向量AB*向量BC = AB * BC * sin ∠ABC,而叉积的绝对值其实就是S△ABC/2

对于平面上的一些点,我们要求凸包上所有的点,可以使用Graham算法 时间复杂度O(nlogn)


思路

先找到最左下的点,把其他的点按叉积排序。然后维护一个堆栈,每次利用叉积和栈顶比较判断当前枚举到的点是否是凸包上的点,是则弹出栈顶元素
具体算法Click here

  • 周长
    直接所有相邻两点距离相加

  • 面积
    多边形面积直接利用公式,用叉积计算


常熟巨大的丑陋代码

# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <string.h>
# include <math.h>
# include <algorithm>
# define RG register
# define IL inline
# define ll long long
# define mem(a, b) memset(a, b, sizeof(a))
# define Min(a, b) (((a) > (b)) ? (b) : (a))
# define Max(a, b) (((a) < (b)) ? (b) : (a))
# define Sqr(a) ((a) * (a))
using namespace std; const int MAXN = 50001;
int n, top;
struct Point{
double x, y, len;
} p[MAXN], Point_A, s[MAXN]; //最左下的点
//求叉积(向量ab,向量ac)
IL double Cross(Point a, Point b, Point c){
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
} IL double Dis(Point a, Point b){
return sqrt(Sqr(a.x - b.x) + Sqr(a.y - b.y));
}
//极角排序
IL bool Cmp(Point a, Point b){
RG double x = Cross(Point_A, a, b);
if(x > 0) return 1;
else if(x < 0) return 0;
a.len = Dis(Point_A, a);
b.len = Dis(Point_A, b);
return a.len < b.len;
}
//查找起始点,最左下
IL void Find(){
RG int temp = 0;
RG Point a = p[1];
for(RG int i = 2; i <= n; i++)
if(p[i].y < a.y || p[i].y == a.y && p[i].x < a.x){
a = p[i];
temp = i;
}
p[temp] = p[1];
p[1] = a;
Point_A = a;//保存起始点
}
//求凸包周长
IL double Length(){
RG double sum = 0;
for(RG int i = 1; i <= top; i++)
sum += Dis(s[i - 1], s[i]);
return sum;
}
//计算面积
IL double Area(){
RG double sum = 0;
for(RG int i = 1; i < top - 1; i++)
sum += Cross(s[0], s[i], s[i + 1]);
sum = fabs(sum) / 2;
return sum;
} IL void Graham(){
Find();
sort(p + 2, p + n + 1, Cmp);
s[0] = p[1]; s[1] = p[2];
for(RG int i = 3; i <= n; i++){
while(Cross(s[top - 1], s[top], p[i]) <= 0 && top) top--;
s[++top] = p[i];
}
s[++top] = p[1];
} int main(){
while(~scanf("%d", &n) && n){
top = 1;
for(RG int i = 1; i <= n; i++)
scanf("%lf%lf", &p[i].x, &p[i].y);
Graham();
cout << top << " " << length() << " " << Area() << endl;
}
return 0;
}

板子题 1.Surround the Trees HDU - 1392 2.Cows POJ - 3348

Graham凸包算法简介的更多相关文章

  1. Graham Scan凸包算法

    获得凸包的算法可以算是计算几何中最基础的算法之一了.寻找凸包的算法有很多种,Graham Scan算法是一种十分简单高效的二维凸包算法,能够在O(nlogn)的时间内找到凸包. 首先介绍一下二维向量的 ...

  2. 二维凸包 Graham扫描算法

    题目链接: http://poj.org/problem?id=1113 求下列点的凸包 求得凸包如下: Graham扫描算法: 找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小 ...

  3. 凸包Graham Scan算法实现

    凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理.一般算法是将共线 ...

  4. POJ 2187 旋转卡壳 + 水平序 Graham 扫描算法 + 运算符重载

    水平序 Graham 扫描算法: 计算二维凸包的时候可以用到,Graham 扫描算法有水平序和极角序两种. 极角序算法能一次确定整个凸包, 但是计算极角需要用到三角函数,速度较慢,精度较差,特殊情况较 ...

  5. 圈水池 nyoj 78 凸包算法

    圈水池 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水, ...

  6. POJ1113:Wall (凸包算法学习)

    题意: 给你一个由n个点构成的多边形城堡(看成二维),按顺序给你n个点,相邻两个点相连. 让你围着这个多边形城堡建一个围墙,城堡任意一点到围墙的距离要求大于等于L,让你求这个围墙的最小周长(看成二维平 ...

  7. webrtc 的回声抵消(aec、aecm)算法简介(转)

    webrtc 的回声抵消(aec.aecm)算法简介        webrtc 的回声抵消(aec.aecm)算法主要包括以下几个重要模块:1.回声时延估计 2.NLMS(归一化最小均方自适应算法) ...

  8. AES算法简介

    AES算法简介 一. AES的结构 1.总体结构 明文分组的长度为128位即16字节,密钥长度可以为16,24或者32字节(128,192,256位).根据密钥的长度,算法被称为AES-128,AES ...

  9. openlayer的凸包算法实现

    最近在要实现一个openlayer的凸多边形,也遇到了不小的坑,就记录一下 1.具体的需求: 通过在界面点击,获取点击是的坐标点,来绘制一个凸多边形. 2.思考过程: 1)首先,我们得先获取点击事件发 ...

随机推荐

  1. python学习:备份文档并压缩为zip格式

    import os import time source = ['/root/notes'] target_dir = '/root/backup' if not os.path.exists(tar ...

  2. python学习:函数的递归调用

    计算阶层   普通方法: -使用循环   #!/usr/bin/python   def factorial(n):     sum = 1     for i in range(1,n+1):   ...

  3. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

  4. Django在form提交CSRF验证失败. 相应中断问题

    CSRF验证失败. 相应中断. 1).首先,我们可以先看一下出现问题的所在的原因. Your browser is accepting cookies. The view function passe ...

  5. 1014. Waiting in Line (模拟)

    n个窗口就有n个队列,模拟这n个队列就可以了.需要注意的是,一个人在选择排队窗口的时候,他会选择排队人数最少的窗口,如果存在多个窗口排队的人数相同,那么他会选择编码最小的窗口. Note that s ...

  6. javascript中快速求数组的全部元素的相加之和

    js中快速求数组的全部元素的相加之和: var arr = [1,2,3,4,5];var sum = eval(arr.join('+')); console.log(sum); 运行结果: 15

  7. JavaScript基础教程2-20160612

    1.JavaScript之操作html元素,Dom Dom是抽象出来的网页对象,需要了解面向对象的思想:调用对象下的方法实现相应的功能 使用JS调用dom来创建标签. //document是网页对象 ...

  8. List,Set,Map

    1.Collection 和 Map 的区别 容器内每个为之所存储的元素个数不同.Collection类型者,每个位置只有一个元素.List,SetMap类型者,持有 key-value pair,像 ...

  9. SDP(9):MongoDB-Scala - data access and modeling

    MongoDB是一种文件型数据库,对数据格式没有硬性要求,所以可以实现灵活多变的数据存储和读取.MongoDB又是一种分布式数据库,与传统关系数据库不同的是,分布式数据库不支持table-join,所 ...

  10. linux 搭建CA服务器 http+ssl mail+ssl 扫描与抓包

    搭建CA服务器 CA服务是给服务器发放数字证书,被通信双方信任,独立的第三方机构 国内常见的CA机构 中国金融认证中心(CFCA) 中国电信安全认证中心(CTCA) 北京数字证书认证中心(BJCA) ...