先说下基础知识,不然不好理解后面的东西

两向量的X乘p1(x1,y1),p2(x2,y2)

p1Xp2如果小于零则说明  p1在p2的逆时针方向

如果大于零则说明 p1在p2的顺时针方向

struct node{
double x,y;
node friend operator -(node a,node b)//对减法符号进行重载
{
return {a.x-b.x,a.y-b.y};
}
}p[],s[];
double X(node a,node b){
return a.x*b.y-a.y*b.x;
}

这个方法很有用处。比如判断一个点是否在一条线段的左边还是右边,可以用X乘来判断,或者判断两条线段是否相交

接着说说凸包    Graham扫描法

1.在平面上一些散乱的点,首先  找找到这些点中处于最左下方的点

        for(int i=;i<=N;i++)
cin>>p[i].x>>p[i].y;
int k=;
for(int i=;i<=N;i++)
{
if(p[i].y<p[k].y||(p[k].y==p[i].y&&p[i].x<p[k].x))
k=i;
}
swap(p[],p[k]);

2.对这些点进行排序。把按照极角(polar angle)从小到大排序(以 p1为极点),极角相同的点按照到的距离从小到大排序。

int cmp(node a,node b)
{
double x=X(a-p[],b-p[]);//以p[1]为极点,通过X乘来判断 if(x>) return ;//让a处于b的顺时针
if(x==&&dis(a,p[])<dis(b,p[]))return ;//角度相同看距离
return ;
} sort(p+,p+N+,cmp);

3.再开一个结构体数组s 来储存凸包最外围的点,也就是结果,这个有点容易让人搞迷。

遍历剩下的点,while循环把发现不是凸包顶点的点移除出去,因为当逆时针遍历凸包时,我们应该在每个顶点向左转。因此当while循环发现在一个顶点处没有向左转时,就把该顶点移除出去。

至于如何判断向左向右则是根据叉积来判断,前面我们已经解决过这个问题了

double multi(node a,node b,node c)
{
return X(b-a,c-a);
}    s[]=p[];
s[]=p[];
int t=;
for(int i=;i<=N;i++)
{
// 发现在栈里边一个顶点处没有向左转时,就把该顶点移除出去
while(t>=&&multi(s[t-],s[t],p[i])<=) t--;
s[++t]=p[i];
}

这个是求凸包的周长的

hdu1392    http://acm.hdu.edu.cn/showproblem.php?pid=1392

算是模板题吧

#include<bits/stdc++.h>
using namespace std; struct point{
double x,y;
point friend operator -(point a,point b)
{return {a.x-b.x,a.y-b.y};}
}p[],s[];
double dis(point a,point b)
{
point c=a-b;
return sqrt(c.x*c.x+c.y*c.y);
}
double X(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
int cmp(point a,point b)
{
double x=X(a-p[],b-p[]); if(x>) return ;
if(x==&&dis(a,p[])<dis(b,p[])) return ;
return ;
}
double multi(point p1,point p2,point p3)
{
return X(p2-p1,p3-p1);
}
int main()
{
int N;
while(scanf("%d",&N),N)
{
for(int i=;i<=N;i++) cin>>p[i].x>>p[i].y; if(N==)
{
printf("0.00\n");
continue;
}
else if(N==)
{
printf("%.2lf\n",dis(p[],p[]));
continue;
} int k=;
for(int i=;i<=N;i++)
if(p[i].y<p[k].y||(p[i].y==p[k].y&&p[i].x<p[k].x))k=i;
swap(p[],p[k]); sort(p+,p++N,cmp); s[]=p[];
s[]=p[];
int t=;
for(int i=;i<=N;i++)
{
while(t>=&&multi(s[t-],s[t],p[i])<=) t--;
s[++t]=p[i];
}
double sum=;
for(int i=;i<t;i++)
{
sum+=dis(s[i],s[i+]);
}
printf("%.2lf\n",sum+dis(s[],s[t]));
}
return ;
}

emmm  再来个求任意多边形的面积

struct Point {
double x, y;
}; //计算任意多边形的面积,顶点按照顺时针或者逆时针方向排列
double polygon_area(Point *p, int n)
{
if(n < ) return ; double sum = ;
p[n + ] = p[];
for(int i = ; i <= n; i++)
sum += p[i].x * p[i + ].y - p[i].y * p[i + ].x;//可以理解为不管这个多边形在哪,都以原点为分割点,就算原点在外面也可以算出,因为有正负可以抵消掉多余的
sum = fabs(sum / 2.0);
return sum;
}

再来个求面积均匀的多边形重心

需要把多边形以p[0]为分界点  分成n-2个三角形,求出这些三角形的重心(i,j),乘以该三角形的面积,如上图公式

#include<bits/stdc++.h>
using namespace std;
struct node{
double x,y;
node friend operator -(node a,node b)
{
return {a.x-b.x,a.y-b.y};
}
double friend operator *(node a,node b)//对*进行重载 node*node 相当于X乘
{
return a.x*b.y-a.y*b.x;
}
}a[];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=;i<=n;i++) cin>>a[i].x>>a[i].y; double S=,X=,Y=;
for(int i=;i<n;i++)
{
double x=(a[i]-a[])*(a[i+]-a[]);//这个乘和下面的不一样,这时X乘,求出三角形面积
X+=(a[].x+a[i].x+a[i+].x)*x;//重心(没除以3)乘以面积
Y+=(a[].y+a[i].y+a[i+].y)*x;
S+=x;
}
printf("%.2lf %.2lf\n",X/S/(double),Y/S/(double));//除以3为重心
}
return ;
}

凸包算法(Graham扫描法)详解的更多相关文章

  1. JVM垃圾回收算法及回收器详解

    引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...

  2. 凸包模板——Graham扫描法

    凸包模板--Graham扫描法 First 标签: 数学方法--计算几何 题目:洛谷P2742[模板]二维凸包/[USACO5.1]圈奶牛Fencing the Cows yyb的讲解:https:/ ...

  3. 【机器学习】【条件随机场CRF-2】CRF的预测算法之维特比算法(viterbi alg) 详解 + 示例讲解 + Python实现

    1.CRF的预测算法条件随机场的预测算法是给定条件随机场P(Y|X)和输入序列(观测序列)x,求条件概率最大的输出序列(标记序列)y*,即对观测序列进行标注.条件随机场的预测算法是著名的维特比算法(V ...

  4. 凸包(Convex Hull)构造算法——Graham扫描法

    凸包(Convex Hull) 在图形学中,凸包是一个非常重要的概念.简明的说,在平面中给出N个点,找出一个由其中某些点作为顶点组成的凸多边形,恰好能围住所有的N个点. 这十分像是在一块木板上钉了N个 ...

  5. c++ LeetCode(初级数组篇)十一道算法例题代码详解(一)

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/10940636.html 唉!最近忙着面试找实习,然后都是面试的很多是leetcode的算法题, ...

  6. 最短路径Floyd算法【图文详解】

    Floyd算法 1.定义概览 Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被 ...

  7. KMP算法 Next数组详解

    题面 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百 ...

  8. Dijkstra算法之 Java详解

    转载:http://www.cnblogs.com/skywang12345/ 迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主 ...

  9. $PollardRho$ 算法及其优化详解

    \(PollardRho\) 算法总结: Pollard Rho是一个非常玄学的算法,用于在\(O(n^{1/4})\)的期望时间复杂度内计算合数n的某个非平凡因子(除了1和它本身以外能整除它的数). ...

  10. 凸包入门(Graham扫描法)(A - Wall POJ - 1113)

    题目链接:https://cn.vjudge.net/contest/276359#problem/A 题目大意:有一个国王,要在自己的城堡周围建立围墙,要求围墙能把城堡全部围起来,并且围墙距离城堡的 ...

随机推荐

  1. 工程命名为***&***出现的问题: LaunchScreen.xib: Line 20: EntityRef: expecting ';'

    今天新建一个项目命名为28 & 29. extern&static,  然后cmd + R运行,居然碰到了编译错误. 当时就奇怪了,怎么会这样呢?报错内容如下: 开始还以为新安装的Xc ...

  2. Spring知识点小结(二)

    一.配置非自定义的Bean(数据源DataSource模型) DBCP数据源:        导入dbcp的jar包:dbcp+pool+connector                代码实现:  ...

  3. laravel 5.7 resources 本地化 简体中文

    使用方法: 新建目录[项目目录/resources/lang/zh] 按以下内容创建文件,并将内容复制到文件中 修改 config/app.php 'locale' => 'zh', 'fall ...

  4. svn出现目标计算机积极拒绝无法链接

    这是由于没有启动服务器端监控的原因,只需要执行以下代码即可 svnserve -d --listen-port 8000 -r /opt/svn

  5. MySQL---事务、函数

    事务 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性. delimiter \\ create PROCEDURE p1( OUT ...

  6. html5中audio支持音频格式

    HTML5 Audio标签能够支持wav, mp3, ogg, acc, webm等格式,但有个很重要的音乐文件格式midi(扩展名mid)却在各大浏览器中都没有内置的支持.不是所有的浏览器都支持MP ...

  7. CSS中的动画

    1.transition 在CSS3中,可以通过transition为元素从一种样式变换为另外一种样式的过程添加效果. transition为简写属性,用于在一个属性中设置四个过渡属性,分别是: tr ...

  8. OrientDB部署

    1. 环境准备 操作系统: Centos6.8 内存: 8G(分布式部署时建议4G及以上,否则需要手动修改JVM配置) JDK: 建议jdk8版本(3.0版本要求jdk8) 环境变量:需配置JAVA_ ...

  9. C# 发送Http协议 模拟 Post Get请求

    1.参数 paramsValue的格式 要和 Reques.ContentType一致, 如果 contentype  "application/x-www-form-urlencoded& ...

  10. C# 设计模式之 单例模式

    单例模式三种写法: 第一种最简单,但没有考虑线程安全,在多线程时可能会出问题,不过俺从没看过出错的现象,表鄙视我…… public class Singleton{    private static ...