凸包算法学习

本文介绍向量的基本概念及运算,包括加法、减法、点积和叉积等,并探讨其几何意义。此外,还介绍了平面凸包的概念及其求解方法——Graham扫描法,通过实例代码展示了如何实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

向量

  1. 既有大小,又有方向的量,如速度

  2. 表示方法:字母上加箭头 a → \overrightarrow{a} a

  3. 向量的大小:表示为 ∣   a   → ∣ |\overrightarrow{ \ a \ }|  a  ∣   A B   → ∣ |\overrightarrow{ \ AB \ }|  AB 

  4. 在平面直角坐标系中,将向量 a → \overrightarrow{a} a 平移,使起点与原点重合,终点位于点 ( x , y ) (x,y) (x,y),则实数对 ( x , y ) (x,y) (x,y)为向量   a   → \overrightarrow{ \ a \ }  a  的坐标,记为   a   → = ( x , y ) \overrightarrow{ \ a \ }=(x,y)  a  =(x,y)

  5. 加法:   A   → +   B   → = ( x 1 + x 2 , y 1 + y 2 ) \overrightarrow{ \ A \ }+\overrightarrow{ \ B \ }=(x_1+x_2,y_1+y_2)  A  + B  =(x1+x2,y1+y2)

  6. 减法:   A   → −   B   → = ( x 1 − x 2 , y 1 − y 2 ) \overrightarrow{ \ A \ }-\overrightarrow{ \ B \ }=(x_1-x_2,y_1-y_2)  A   B  =(x1x2,y1y2)

  7. 向量加减法满足交换律和结合律

  8. A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2),则 A B → = B − A \overrightarrow{AB}=B-A AB =BA

点积

  1. 点积就是 a ⋅ b = x 1 x 2 + y 1 y 2 a⋅b=x_1x_2+y_1y_2 ab=x1x2+y1y2
  2. 几何意义:两个向量的夹角
  3. 点积的性质:
  • a ⋅ b = 0 a⋅b=0 ab=0,则 a ⊥ b a\bot b ab
  • a ⋅ b < 0 a⋅b<0 ab<0,则夹角 > 9 0 ∘ >90^\circ >90
  • a ⋅ b > 0 a⋅b>0 ab>0,则夹角 < 9 0 ∘ <90^\circ <90

叉积

  1. 叉积就是 a × b = x 1 y 2 − x 2 y 1 a\times b=x_1y_2-x_2y_1 a×b=x1y2x2y1
  2. 几何意义:两个向量起点共点时,形成的四边形的面积
  3. 叉积的性质:
  • a × b = 0 a\times b=0 a×b=0 a a a b b b平行
  • a × b > 0 a\times b>0 a×b>0 a a a b b b顺时针方向
  • a × b < 0 a\times b<0 a×b<0 a a a b b b逆时针方向

凸包

平面凸包指能覆盖平面上 n n n个点的最小的凸四边形,我们可以使用Graham扫描法来求点和周长。

Graham扫描法的步骤如下:

  1. 找到最左下的点作为原点
  2. 将其他点与原点连一条线段,计算出线段与水平线的夹角,按夹角从小到大排序。若夹角相同,优先选择距离原点近的点。
  3. 维护一个栈,将前两个点放进栈中,遍历3~n。设栈顶前一个点为 A 1 A_1 A1,栈顶的点为 A 2 A_2 A2,枚举到的点为 A 3 A_3 A3
  • 如果 A 1 A 3 A_1A_3 A1A3 A 1 A 2 A_1A_2 A1A2顺时针方向,则 A 2 A_2 A2在凹陷处,应该删除,栈顶元素出栈,继续比较
  • 如果 A 1 A 3 A_1A_3 A1A3 A 1 A 2 A_1A_2 A1A2顺时针方向,则将 A 3 A_3 A3压入栈中
  1. 遍历完后,栈中的点就是凸包上的点,周长为 ∣ s 1 s t o p → ∣ + ∑ i = 1 t o p ∣ s i s i + 1 → ∣ |\overrightarrow{s_1s_{top}}|+\sum\limits_{i=1}^{top}|\overrightarrow{s_is_{i+1}}| s1stop +i=1topsisi+1

例题

P2742 [USACO5.1]Fencing the Cows

code

#include<bits/stdc++.h>
using namespace std;
int n,bz=1,tp,h[100005];
double ans=0;
struct node{
    double x,y;
}w[100005];
bool pt(node v1,node v2,node v3){
    if((v2.x-v1.x)*(v3.y-v1.y)-(v2.y-v1.y)*(v3.x-v1.x)<=0) return 1;
    return 0;
}
double dis(node ax,node bx){
    return sqrt((ax.x-bx.x)*(ax.x-bx.x)+(ax.y-bx.y)*(ax.y-bx.y));
}
bool cmp(node ax,node bx){
	double v1=atan2(ax.y-w[1].y,ax.x-w[1].x),v2=atan2(bx.y-w[1].y,bx.x-w[1].x);
    if(v1==v2) return dis(w[1],ax)<dis(w[1],bx);
    return v1<v2;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&w[i].x,&w[i].y);
        if(w[bz].y>w[i].y||w[bz].y==w[i].y&&w[bz].x>w[i].x) bz=i;
    }
    swap(w[1],w[bz]);
    sort(w+2,w+n+1,cmp);
    h[++tp]=1;h[++tp]=2;
    for(int i=3;i<=n;i++){
        if(w[i].x==w[i-1].x&&w[i].y==w[i-1].y) continue;
        while(tp>=2&&pt(w[h[tp-1]],w[h[tp]],w[i])) --tp;
        h[++tp]=i;
    }
    h[tp+1]=h[1];
    for(int i=1;i<=tp;i++){
        ans+=dis(w[h[i]],w[h[i+1]]);
    }
    printf("%.2f",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值