codeforces-go中的几何模板:计算几何算法汇总

codeforces-go中的几何模板:计算几何算法汇总

【免费下载链接】codeforces-go 算法竞赛模板库 by 灵茶山艾府 💭💡🎈 【免费下载链接】codeforces-go 项目地址: https://gitcode.com/GitHub_Trending/co/codeforces-go

概述

计算几何(Computational Geometry)是算法竞赛中的重要领域,涉及点、线、面等几何元素的计算与处理。codeforces-go项目的copypasta模块提供了全面的几何算法模板,涵盖向量运算、线段处理、圆相关计算等核心功能。本文将系统介绍geometry.go中的关键实现,帮助开发者快速掌握计算几何的实用技巧。

核心数据结构

向量与点

向量(Vector)是计算几何的基础,用于表示点和方向。在geometry.go中,向量通过vec结构体实现,包含x和y两个整数分量:

type vec struct{ x, y int }

该结构体提供了丰富的向量运算方法,包括:

  • sub(b vec) vec:向量减法
  • dot(b vec) int:点积(Dot Product)
  • det(b vec) int:叉积(Cross Product)的z分量值
  • len2() int:向量长度的平方
  • rotateCCW90() vec:逆时针旋转90度

线与线段

直线和线段通过line结构体表示,包含两个端点:

type line struct{ p1, p2 vec }

关键方法包括:

  • vec() vec:获取方向向量
  • onSeg(a vec) bool:判断点是否在线段上
  • intersection(b lineF) vecF:计算两直线交点

圆通过circle结构体表示,包含圆心和半径:

type circle struct {
    vec  // 圆心坐标
    r int // 半径
}

提供了圆心角对应点计算、两圆交点求解等功能。

基础运算

点积与叉积

点积和叉积是向量运算的核心,在geometry.go中实现如下:

// 点积:判断两向量方向关系
func (a vec) dot(b vec) int { return a.x*b.x + a.y*b.y }

// 叉积:判断两向量相对位置
func (a vec) det(b vec) int { return a.x*b.y - a.y*b.x }

点积结果的符号表示两向量的夹角关系:

  • 正:夹角为锐角
  • 零:垂直
  • 负:夹角为钝角

叉积结果的符号表示相对位置:

  • 正:b在a左侧
  • 零:共线
  • 负:b在a右侧

距离计算

距离计算是几何问题的基础,实现了多种距离相关方法:

// 两点间距离的平方
func (a vec) dis2(b vec) int { return b.sub(a).len2() }

// 两点间距离
func (a vec) dis(b vec) float64 { return b.sub(a).len() }

// 点到直线的距离
func (a vecF) disToLine(l lineF) float64 {
    v, p1a := l.vec(), a.sub(l.p1)
    return math.Abs(v.det(p1a)) / v.len()
}

几何算法应用

极角排序

极角排序用于将平面上的点按与原点的夹角排序,在凸包计算等场景中广泛应用:

func polarAngleSort(ps []vec) {
    // 按极角 (-π, π] 排序
    sort.Slice(ps, func(i, j int) bool { 
        return ps[i].polarAngle() < ps[j].polarAngle() 
    })
    
    // 优化:将向量统一转为正方向后用叉积排序
    for i := range ps {
        ps[i] = ps[i].up()
    }
    sort.Slice(ps, func(i, j int) bool { 
        return ps[i].det(ps[j]) > 0 
    })
}

三角形五心计算

几何模板实现了三角形的外心、垂心和内心计算:

// 外心(外接圆圆心)
func circumcenter(a, b, c vecF) vecF {
    a1, b1, a2, b2 := b.x-a.x, b.y-a.y, c.x-a.x, c.y-a.y
    c1, c2, d := a1*a1+b1*b1, a2*a2+b2*b2, 2*(a1*b2-a2*b1)
    if math.Abs(d) < eps { // 三点共线
        return vecF{math.NaN(), math.NaN()}
    }
    return vecF{a.x + (c1*b2-c2*b1)/d, a.y + (a1*c2-a2*c1)/d}
}

// 垂心
func orthocenter(a, b, c vecF) vecF {
    return a.add(b).add(c).sub(circumcenter(a, b, c).mul(2))
}

// 内心(角平分线交点)
func incenter(a, b, c vecF) vecF {
    bc, ac, ab := b.dis(c), a.dis(c), a.dis(b)
    sum := bc + ac + ab
    return vecF{(bc*a.x + ac*b.x + ab*c.x)/sum, (bc*a.y + ac*b.y + ab*c.y)/sum}
}

最小圆覆盖

最小圆覆盖问题要求找到能覆盖所有给定点的最小圆,采用Welzl's算法实现:

func smallestEnclosingDisc(ps []vecF) circleF {
    rand.Shuffle(len(ps), func(i, j int) { ps[i], ps[j] = ps[j], ps[i] })
    o := ps[0]
    r2 := 0.0
    for i, p := range ps {
        if p.dis2(o) < r2+eps {
            continue
        }
        o, r2 = p, 0.0
        for j, q := range ps[:i] {
            if q.dis2(o) < r2+eps {
                continue
            }
            o = vecF{(p.x + q.x)/2, (p.y + q.y)/2}
            r2 = p.dis2(o)
            for _, x := range ps[:j] {
                if x.dis2(o) > r2+eps {
                    o = circumcenter(p, q, x)
                    r2 = p.dis2(o)
                }
            }
        }
    }
    return circleF{o, math.Sqrt(r2)}
}

该算法通过随机增量法实现,期望时间复杂度为O(n)。

圆与矩形碰撞检测

判断圆与矩形是否重叠是游戏开发等场景的常见问题:

func isCircleRectangleOverlap(r, ox, oy, x1, y1, x2, y2 int) bool {
    // 计算圆心到矩形的最近点
    cx := clamp(ox, x1, x2)
    cy := clamp(oy, y1, y2)
    // 计算最近点与圆心的距离平方
    dx, dy := ox-cx, oy-cy
    return dx*dx + dy*dy <= r*r
}

精度控制

计算几何中浮点数精度是关键问题,geometry.go采用以下策略:

  1. 定义全局精度常量:
const eps = 1e-8
  1. 比较时使用精度控制:
func (a vecF) equals(b vecF) bool { 
    return math.Abs(a.x-b.x) < eps && math.Abs(a.y-b.y) < eps 
}
  1. 大浮点数比较采用相对误差:
// 大浮点数相等判断
a == b   a*(1-eps) < b && b < a*(1+eps)

应用场景

算法竞赛

codeforces-go的几何模板已在多项算法竞赛题目中得到应用,例如:

实际应用

几何算法在多个领域有广泛应用:

  • 计算机图形学:碰撞检测、光线追踪
  • 地理信息系统:空间分析、路径规划
  • 机器人技术:运动规划、障碍物规避

总结与扩展

codeforces-go的几何模板提供了计算几何的核心实现,涵盖从基础向量运算到复杂几何问题求解的完整功能。开发者可基于此模板:

  1. 扩展三维几何功能
  2. 优化特定场景的精度问题
  3. 结合具体问题开发新算法

建议深入阅读geometry.go源码,并通过实际题目练习巩固理解。后续可关注计算几何高级主题,如Voronoi图、 arrangements等。

资源与参考

  • 官方文档:geometry.go
  • 推荐读物:《计算几何:算法与应用》
  • 在线资源:OI-Wiki 计算几何
  • 练习题集:Codeforces Geometry标签题目

【免费下载链接】codeforces-go 算法竞赛模板库 by 灵茶山艾府 💭💡🎈 【免费下载链接】codeforces-go 项目地址: https://gitcode.com/GitHub_Trending/co/codeforces-go

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值