向量积&&凸包算法
参考:Thanks
百度百科
http://blog.csdn.net/keng_s/article/details/52131034
https://www.cnblogs.com/aiguona/p/7232243.html
一定要有耐心,仔细的看。(#^.^#)
预备:
向量积
概念:
向量积,数学中又称外积、叉积,物理中称矢积、叉乘,是一种在向量空间中向量的二元运算。与点积不同,它的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量和垂直。
计算:a,b,c均为向量
向量的叉乘,即求同时垂直两个向量的向量,即c垂直于a,同时c垂直于b(a与c的夹角为90°,b与c的夹角为90°)
c = a×b = (a.y*b.z-b.y*a.z , b.x*a.z-a.x*b.z , a.x*b.y-b.x*a.y)

以上图为例a(1,0,0),b(0,1,0),c=a×b = (0,0,1)
相关:
向量积|c|=|a×b|=|a| |b|sin<a,b>
即c的长度在数值上等于以a,b,夹角为θ组成的平行四边形的面积。
如果a,b的叉积|c|的数值>0 说明 b在a的逆时针方向
|c|的数值=0 说明 b和a在一条直线上
|c|的数值<0 说明 b在a的顺时针方向
===========================================================分割线
凸包
概念:
1.在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称 为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的凸组合来构造.
2. 在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
3. 用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。
定义:
1.点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。下图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。

2.一组平面上的点,求一个包含所有点的最小的凸多边形,这就是凸包问题了。这可以形象地想成这样:在地上放置一些不可移动的木桩,用一根绳子把他们尽量紧地圈起来,并且为凸边形,这就是凸包了。
常用求法:
Graham扫描法
过程:
1.在所有点中选取y坐标最小的一点H,当作基点。如果存在多个点的y坐标都为最小值,则选取x坐标最小的一点。。坐标相同的点应排除。
然后按照其它各点p和基点构成的向量<H,p>;与x轴的夹角进行排序,夹角由大至小进行顺时针扫描,反之则进行逆时针扫描。实现中无需求得夹角,只需根据余弦定理求出向量夹角的余弦值即可。
以下图为例,基点为H,根据夹角由小至大排序后依次为H,K,C,D,L,F,G,E,I,B,A,J。下面进行逆时针扫描。

2.线段<H,K>;一定在凸包上,接着加入C。假设线段<K,C>;也在凸包上,因为就H,K,C三点而言,它们的凸包就是由此三点所组成。但是接下来加入D时会发现,线段<K,D>;才会在凸包上,所以将线段<K,C>;排除,C点不可能是凸包。
3. 即当加入一点时,必须考虑到前面的线段是否在凸包上。
基点开始,凸包上每条相临的线段的旋转方向应该一致,并与扫描的方向相反。
如果发现新加的点使得新线段与上线段的旋转方向发生变化,则可判定上一点必然不在凸包上。实现时可用向量叉积进行判断。
设新加入的点为P[n+1],上一点为P[n],再上一点为P[n-1]。顺时针扫描时,如果向量
(P[n-1],P[n])与(P[n],P[n+1])的叉积为正(逆时针扫描判断是否为负),则将上一点删除。删除过程需要回溯,将之前所有叉积符号相反的点都删除,然后将新点加入凸包。
在上图中,加入K点时,由于线段<H,C>要旋转到<H,K>的角度,为顺时针旋转,所以C点不在凸包上,应该删除,保留K点。接着加入D点,由于线段<K,D>要旋转到<H,K>的角度,为逆时针旋转,故D点保留。按照上述步骤进行扫描,直到点集中所有的点都遍历完成,即得到凸包.


模板:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define PI 3.1415926535
#define DB double
#define eps 1e-8
using namespace std;
const int N=;
int T,n,L;
struct node{
DB x,y;
}d[N],s[N];//d[]存入的所有的点 s[]凸包中所有的点
bool cmp1(node a,node b)
{
if(a.y!=b.y) return a.y<b.y;
else return a.x<b.x;
}
DB Cross(node a1,node a2,node b1,node b2)
{
return (a2.x-a1.x)*(b2.y-b1.y)-(b2.x-b1.x)*(a2.y-a1.y);
}
DB dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
}
bool cmp2(node a,node b)//极角排序,原理见紫色部分
{
DB m=Cross(d[],a,d[],b);
if(m>) return ;
else if(m==) return dis(d[],a)<dis(d[],b);
return ;
}
int top;
DB ans;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i)scanf("%lf%lf",&d[i].x,&d[i].y);
sort(d+,d+n+,cmp1);
s[++top]=d[];
sort(d+,d+n+,cmp2);
s[++top]=d[];
for(int i=;i<=n;++i)
{
while(top>= && Cross(s[top-],s[top],s[top],d[i])<=) top--;
//控制<0或<=0可以控制重点,共线的,具体视题目而定
s[++top]=d[i];
}
for(int i=;i<top;++i)ans+=dis(s[i],s[i+]);
ans+=dis(s[],s[top]);
printf("%.2lf\n",ans);
return ;
}
盛开吧这世界最美丽的花。
向量积&&凸包算法的更多相关文章
- openlayer的凸包算法实现
最近在要实现一个openlayer的凸多边形,也遇到了不小的坑,就记录一下 1.具体的需求: 通过在界面点击,获取点击是的坐标点,来绘制一个凸多边形. 2.思考过程: 1)首先,我们得先获取点击事件发 ...
- 圈水池 nyoj 78 凸包算法
圈水池 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水, ...
- Graham Scan凸包算法
获得凸包的算法可以算是计算几何中最基础的算法之一了.寻找凸包的算法有很多种,Graham Scan算法是一种十分简单高效的二维凸包算法,能够在O(nlogn)的时间内找到凸包. 首先介绍一下二维向量的 ...
- 计算几何-凸包算法 Python实现与Matlab动画演示
凸包算法是计算几何中的最经典问题之一了.给定一个点集,计算其凸包.凸包是什么就不罗嗦了 本文给出了<计算几何——算法与应用>中一书所列凸包算法的Python实现和Matlab实现,并给出了 ...
- 587. Erect the Fence(凸包算法)
问题 给定一群树的坐标点,画个围栏把所有树围起来(凸包). 至少有一棵树,输入和输出没有顺序. Input: [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]] Output: ...
- Beauty Contest(graham求凸包算法)
Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 25256 Accepted: 7756 Description Bess ...
- Graham凸包算法简介
凸包真是一个神奇的算法.. 概念 凸包,我理解为凸多边形 叉积 对于向量AB和向量BC,记向量AB*向量BC = AB * BC * sin ∠ABC,而叉积的绝对值其实就是S△ABC/2 对于平面上 ...
- POJ1113:Wall (凸包算法学习)
题意: 给你一个由n个点构成的多边形城堡(看成二维),按顺序给你n个点,相邻两个点相连. 让你围着这个多边形城堡建一个围墙,城堡任意一点到围墙的距离要求大于等于L,让你求这个围墙的最小周长(看成二维平 ...
- 凸包算法(Graham扫描法)详解
先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明 p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...
随机推荐
- oracle 11g不能导出空表的解决方法
在oracle 11g r2中,发现传统的exp居然不能导出空的表,然后查询一下, 发现需要如下的步骤去搞,笔记之. oracle 11g 新增了一个参数:deferred_segment_c ...
- VMware 虚拟化编程(1) — VMDK/VDDK/VixDiskLib/VADP 概念简析
目录 目录 VMDK VDDK VixDiskLib VADP VMDK VMDK(VMware's Virtual Machine Disk Format,VMware 虚拟磁盘格式):简单来说就是 ...
- Docker image 和 volume 的关系
image :镜像 虚拟机容器需要加载image才能运行,镜像中打包了构建好服务的运行环境. Docker images are the basis of containers. An Image i ...
- 升级到mysql5.7无法启动问题解决
漏洞扫描,老项目升级到5.7位成功,启动发现报错:unknown option log_error 线备份my.cnf配置文件, 猜测应该是写法有问题,先把log_error 改成log #log_ ...
- 【ABAP系列】SAP ABAP 关于ALV布局保存选项的讲解
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP ABAP 关于ALV布局保存 ...
- 剑指offer--day09
1.1 题目:栈的压入.弹出序列:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列 ...
- vue 父子component生命周期
如今前端框架都流行组件化,页面元素都可以使用组件进行高度概括,那么处理组件之间的关系就如同处理页面架构一样重要.正确理解组件之间的关系,才能让代码按照我们与预料方式工作.最近参与了一个Vue.js的项 ...
- mysql使用触发器生成唯一订单号,
需求:订单号唯一,并且期望是时间格式加其他字符串, 实现:采用触发机制,在新增时根据新增id值加1作为订单生成的随机且确定唯一的数,因为id唯一: 遇到问题:新增时不能提前知道id值, 解决:取到当前 ...
- python基础-5.1几种常见的排序算法
一.冒泡排序(BubbleSort) 步骤: 比较相邻的元素,如果第一个比第二个大,就交换他们两个. 循环一遍后,最大的数就“浮”到了列表最后的位置. 将剩下的数再次循环,直道所有的排序完成 def ...
- String的相关操作总结
Java中的String与常量池 string是java中的字符串.String类是不可变的,对String类的任何改变,都是返回一个新的String类对象. string是java中的字符串.Str ...