白书16.12凸包

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A

安德鲁算法
安德鲁算法判断凸包需要用到叉积
关于叉积


首先在二维坐标下介绍一些定义:
点:A(x1,y1),B(x2,y2)

向量:向量AB=( x2 - x1 , y2 - y1 )= ( x ,  y );

向量的模 |AB| = sqrt ( x*x+y*y );



向量的点积: 结果为 x1*x2 + y1*y2。

点积的结果是一个数值。

点积的集合意义:我们以向量 a 向向量 b 做垂线,则 | a | * cos(a,b)为 a 在向量 b 上的投影,即点积是一个向量在另一个向量上的投影乘以另一个向量。且满足交换律

应用:可以根据集合意义求两向量的夹角,
cos(a,b) =( 向量a * 向量b ) / (| a | * | b |) =  x1*x2 + y1*y2 / (| a | * | b |)



向量的叉积: 结果为 x1*y2-x2*y1

叉积的结果也是一个向量,是垂直于向量a,b所形成的平面,如果看成三维坐标的话是在 z 轴上,上面结果是它的模。

方向判定:右手定则,(右手半握,大拇指垂直向上,四指右向量a握向b,大拇指的方向就是叉积的方向)

叉积的集合意义:1:其结果是a和b为相邻边形成平行四边形的面积。

2:结果有正有负,有sin(a,b)可知和其夹角有关,夹角大于180°为负值。

3:叉积不满足交换律

应用:

1:通过结果的正负判断两矢量之间的顺逆时针关系

若 a x b > 0表示a在b的顺时针方向上

若 a x b < 0表示a在b的逆时针方向上

若 a x b == 0表示a在b共线,但不确定方向是否相同

在顺时针方向上为凸包
否则是凹进去的。
以此依次加点。
将坐标按照x从小到大排序。
先加上面的凸包 然后加下面的凸包。

凸包

#include <bits/stdc++.h>
using namespace std;
#define mo 100005
struct node
{
    int x,y;
}d[mo],p[mo];

int chaji(node a,node b,node c)//叉积计算
{
    return ((b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x));
}


bool cmp(node a,node b)//坐标点排序
{
    if(a.y!=b.y)return a.y<b.y;
    return a.x<b.x;
}
void run(int n)
{
    sort(d,d+n,cmp);
    int tot=0;
    for(int i=0;i<n;i++)
    {
        while(tot>1&&chaji(p[tot-2],p[tot-1],d[i])<0) tot--;
        p[tot++]=d[i];
    }

    for(int i=n-2;i>=0;i--)
    {
        while(tot>1&&chaji(p[tot-2],p[tot-1],d[i])<0) tot--;
        p[tot++]=d[i];
    }
    cout<<tot-1<<endl;
    for(int i=0;i<tot-1;i++)
    {
        cout<<p[i].x<<' '<<p[i].y<<endl;
    }

}

int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0;i<n;i++)
            cin>>d[i].x>>d[i].y;

        run(n);
    }



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值