随笔 - 4  文章 - 0 评论 - 0 阅读 - 274
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

计算几何

@

凸包

1.定义:给定一些点,求能把所有这些点包含在内的面积最小的多边形,如果是凸多边形则称为凸包;

2.解决方法:

一是 : Graham扫描法 O(nlogn)

二是 : Jarvis步进法 O(nh) h是凸包上的顶点数

基本思路 : "旋转扫除",设定一个参照顶点,逐个旋转到其他顶点,并判断这些顶点是否在凸包上

3.模板代码:

Graham扫描法的变种Andrew算法(更快更稳)

算法做两次扫描,先从最左边的点沿下凸包扫描到最右边,再从最右边的点扫描上凸包扫描到最左边;上凸包和下凸包连起来就是完整的凸包;

具体步骤 :

1 . 将所有点按照横坐标x从小到大进行排序,如果x相同,按y从小到大排序,并且删除重复的点;得到序列{p0,p1,p2,p3....pm}

2 . 从左到右扫描所有点,求下凸包;p0一定在凸包上,是最左边的顶点;然后依次检查{p1,p2,p3....pm},扩展出下凸包;

判断依据 : 如果新点在凸包前进方向的左边,说明在下凸包上,把它加入到凸包;如果在右边,说明拐弯了,删除最后加入凸包的点,继续这个过程,知道检查完所有点;

是否拐弯 : 利用叉积判断(插图)

3 . 从右到左重新扫描所有点求上凸包;

O(nlogn)

4.例题:

hdu 1392 "Surround the Trees"
全解查看博客题解偏
https://blog.csdn.net/gpc_123/article/details/122741291

int Convex_hull(Point *p,int n,Point *ch){
    sort(p, p + n);//对点排序
    n = unique(p, p + n) - p;//去重
    int v = 0;
    //求下凸包,如果p[i]是右拐弯,这个点不在凸包上往回退
    for (int i = 0; i < n;i ++){
        while(v > 1 && sgn(Cross(ch[v - 1] - ch[v - 2],p[i] - ch[v - 2])) <= 0)
            v--;
        ch[v++] = p[i];
    }
    int j = v;
    //求上凸包
    for (int i = n - 2; i >= 0;i --){
        while(v > j && sgn(Cross(ch[v - 1] - ch[v - 2],p[i] - ch[v - 2])) <= 0)
            v--;
        ch[v++] = p[i];
    }
    if(n > 1) v--;
    return v; //返回凸包顶点数
}
posted on   沐白白  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示