zoukankan      html  css  js  c++  java
  • 向量积&&凸包算法

    参考: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点保留。按照上述步骤进行扫描,直到点集中所有的点都遍历完成,即得到凸包.

    复杂度:
    这个算法可以直接在原数据上进行运算,因此空间复杂度为O⑴。但如果将凸包的结果存储到另一数组中,则可能在代码级别进行优化。由于在扫描凸包前要进行排序,因此时间复杂度至少为快速排序的O(nlgn)。后面的扫描过程复杂度为O(n),因此整个算法的复杂度为O(nlgn)。
    模拟图片:

     模板:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define PI 3.1415926535
     7 #define DB double
     8 #define eps 1e-8
     9 using namespace std;
    10 const int N=12000;
    11 int T,n,L;
    12 struct node{
    13     DB x,y;
    14 }d[N],s[N];//d[]存入的所有的点  s[]凸包中所有的点
    15 bool cmp1(node a,node b)
    16 {
    17     if(a.y!=b.y) return a.y<b.y;
    18     else return a.x<b.x;
    19 }
    20 DB Cross(node a1,node a2,node b1,node b2)
    21 {
    22     return (a2.x-a1.x)*(b2.y-b1.y)-(b2.x-b1.x)*(a2.y-a1.y);
    23 }
    24 DB dis(node a,node b)
    25 {
    26     return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
    27 }
    28 bool cmp2(node a,node b)//极角排序,原理见紫色部分 
    29 {
    30     DB m=Cross(d[1],a,d[1],b);
    31     if(m>0) return 1;
    32     else if(m==0) return dis(d[0],a)<dis(d[0],b);
    33     return 0;
    34 }
    35 int top;
    36 DB ans;
    37 int main()
    38 {
    39     scanf("%d",&n);
    40     for(int i=1;i<=n;++i)scanf("%lf%lf",&d[i].x,&d[i].y);
    41     sort(d+1,d+n+1,cmp1);
    42     s[++top]=d[1];
    43     sort(d+2,d+n+1,cmp2);
    44     s[++top]=d[2];
    45     for(int i=3;i<=n;++i)
    46     {
    47         while(top>=2 && Cross(s[top-1],s[top],s[top],d[i])<=0) top--;
    48         //控制<0或<=0可以控制重点,共线的,具体视题目而定 
    49         s[++top]=d[i];
    50     }
    51     for(int i=1;i<top;++i)ans+=dis(s[i],s[i+1]);
    52     ans+=dis(s[1],s[top]);
    53     printf("%.2lf
    ",ans); 
    54    return 0;
    55 }
    View Code

    盛开吧这世界最美丽的花。

  • 相关阅读:
    Java实现继承过程概述
    Java封装概述
    Java中包的介绍
    Java中final关键字概述
    Java继承概述
    mysql服务自动关闭的解决
    Unity3d碰撞检测中碰撞器与触发器的区别
    解决在Game模式下兼容编辑器模式
    GameObject.Find("")只能查找到显示的对象
    层(layer)的设置
  • 原文地址:https://www.cnblogs.com/adelalove/p/8465055.html
Copyright © 2011-2022 走看看