Graham凸包算法简介
凸包真是一个神奇的算法。。
概念
- 凸包,我理解为凸多边形
- 叉积 对于向量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凸包算法简介的更多相关文章
- Graham Scan凸包算法
获得凸包的算法可以算是计算几何中最基础的算法之一了.寻找凸包的算法有很多种,Graham Scan算法是一种十分简单高效的二维凸包算法,能够在O(nlogn)的时间内找到凸包. 首先介绍一下二维向量的 ...
- 二维凸包 Graham扫描算法
题目链接: http://poj.org/problem?id=1113 求下列点的凸包 求得凸包如下: Graham扫描算法: 找出最左下的点,设为一号点,将其它点对一号点连线,按照与x轴的夹角大小 ...
- 凸包Graham Scan算法实现
凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理.一般算法是将共线 ...
- POJ 2187 旋转卡壳 + 水平序 Graham 扫描算法 + 运算符重载
水平序 Graham 扫描算法: 计算二维凸包的时候可以用到,Graham 扫描算法有水平序和极角序两种. 极角序算法能一次确定整个凸包, 但是计算极角需要用到三角函数,速度较慢,精度较差,特殊情况较 ...
- 圈水池 nyoj 78 凸包算法
圈水池 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水, ...
- POJ1113:Wall (凸包算法学习)
题意: 给你一个由n个点构成的多边形城堡(看成二维),按顺序给你n个点,相邻两个点相连. 让你围着这个多边形城堡建一个围墙,城堡任意一点到围墙的距离要求大于等于L,让你求这个围墙的最小周长(看成二维平 ...
- webrtc 的回声抵消(aec、aecm)算法简介(转)
webrtc 的回声抵消(aec.aecm)算法简介 webrtc 的回声抵消(aec.aecm)算法主要包括以下几个重要模块:1.回声时延估计 2.NLMS(归一化最小均方自适应算法) ...
- AES算法简介
AES算法简介 一. AES的结构 1.总体结构 明文分组的长度为128位即16字节,密钥长度可以为16,24或者32字节(128,192,256位).根据密钥的长度,算法被称为AES-128,AES ...
- openlayer的凸包算法实现
最近在要实现一个openlayer的凸多边形,也遇到了不小的坑,就记录一下 1.具体的需求: 通过在界面点击,获取点击是的坐标点,来绘制一个凸多边形. 2.思考过程: 1)首先,我们得先获取点击事件发 ...
随机推荐
- 安装php的memcached模块和扩展支持sasl
memcached的1.2.4及以上增加了CAS(Check and Set)协议,对于同一key的多进行程的并发处理问题.这种情况其实根数据库很像,如果同时有几个进程对同一个表的同一数据进行更新的话 ...
- ecshop QQ邮箱发送邮件服务器配置
ecshop QQ邮箱发送邮件服务器配置 1.邮件服务:采用其他的SMTP服务 2.邮件服务器是否要求加密连接(SSL): 是 此项设置需要php支持openSSL模块 开启方法: a.php.ini ...
- intellij idea maven 工程生成可执行的jar
新建maven 工程 写hello world 修改pom.xml 文件 <build> <pluginManagement> <plugins> <plug ...
- 阿里云Aliyun_server
一.云概念 云主机是基于云计算平台的一种虚拟的主机服务器产品 云服务器(99.999%安全性,扩展性) 特点: 1.资源分配配置灵活,安全性能强. 2.优于VPS和独立服务器产品.通俗的理解: 云主机 ...
- HDU 5056
题意略. 巧妙的尺取法.我们来枚举每个字符str[i],计算以str[i]为结尾的符合题意的串有多少个.那么我们需要处理出str[i]的左边界j,在[j,i]之间的串均为符合题意的 串,那么str[i ...
- 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(2)
第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 为Domain Model添加约束 前一部分, 我们已经把数据库创建出来了. 那么我们先看看这个数据库 ...
- css渲染(一) 字体和文本
一.字体属性 1.默认字体系列 chrome/opera:"宋体" firefox:"微软雅黑" safari/IE:Times,"宋体" ...
- Shell脚本的基本流程控制
if else read -p '请输入分数:' score if [ $score -lt 60 ]; then echo '60分以下' elif [ $score -lt 70 ]; then ...
- Spring boot 整合mybatis
第一步:创建maven项目并添加spring boot依赖: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns ...
- numpy模块中的sum(axis)方法
1.sum函数声明 sum(a, axis=None, dtype=None, out=None, keepdims=<class 'numpy._globals._NoValue'>) ...