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


概念

  • 凸包,我理解为凸多边形
  • 叉积 对于向量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. 关于 IO的同步异步间要描述

    IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口. 比如你打开 ...

  2. testng 异常 截图

    testNG里有一个异常监听类,失败时会执行类里的相关方法 DriverBase 截图类 TestngListenerScreen 异常监听类 Test1 测试类1.DriverBase类 packa ...

  3. Redis进阶实践之十三 Redis的Redis-trib.rb文件详解

    一.简介     事先说明一下,本篇文章不涉及对redis-trib.rb源代码的分析,只是从使用的角度来阐述一下,对第一次使用的人来说很重要.redis-trib.rb是redis官方推出的管理re ...

  4. ERROR namenode.NameNode: Failed to start namenode. java.lang.IllegalArgument

    这个问题一般是配置文件配置没有配置好的原因

  5. 老男孩Python全栈开发(92天全)视频教程 自学笔记05

    day5课程内容: 集成开发环境(IDE) VIM #经典的Linux下的文本编辑器 Eclipse #Java IDE Visual Studio #微软开发的IDE notepad++ subli ...

  6. pep 8 规范的一些记录

    一.pep8起源 龟叔创立Python的初衷里就有创立一个容易阅读的编程语言,所以亲自操刀写了pep8 代码规范,每个项目开始前都要有一个共识,就是自己的代码规范,pep8 就是一个很好的范本. 二. ...

  7. UVALive - 3644 X-Plosives (并查集)

    思路:每一个product都可以作一条边,每次添加一条边,如果这边的加入使得某个集合构成环,就应该refuse,那么就用并查集来判断. AC代码: //#define LOCAL #include & ...

  8. @EnableAsync @Asnc 以及4种拒绝策略

    根据不同的场景,可以选择不同的拒绝策略,如果任务非常重要,线程池队列满了,可以交由调用者线程同步处理. 如果是一些不太重要日志,可以直接丢弃掉. 如果一些可以丢弃,但是又需要知道被丢弃了,可以使用Th ...

  9. ios开发之自定义textView

    自定义textView,从理论上讲很简单,根据需求自定义,比如我在开发中的需求就是现实一个字数的限制以及根据输入的文字改变提示剩余字数,那么开始我的基本思路就是自定义一个View,而里面包含一个子控件 ...

  10. mysql数据库导入导出 查询 修改表记录

    mysql数据导入导出: 导入: 把系统的文件的内容,保存到数据库的表里 导入数据的基本格式:mysql> load data infile "文件名" into table ...