尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

计算几何初步:CCW 与判断两线段的相交性

计算几何初步:CCW 与判断两线段的相交性
📅 发布时间:2026/6/20 19:10:03

本文写于 2025 年 9 月 18 日。

前言

昨天在正睿的“IOI 普及联赛”中,有这样一道题,极大地冲击了本蒟蒻的心灵。赛后查看题解,此题竟然涉及计算几何,这更是本蒟蒻从未涉足的领域。我遂查询资料,学习了 CCW 算法以及用其判断线段是否相交的方法,并迅速写了一个骗得 25 分的代码。借此机会,我想分享一下 CCW 算法及利用其判断两线段是否相交的方法。

CCW 算法

CCW 是 Counter-Clockwise 的缩写,即逆时针方向。顾名思义,此算法用来计算两首尾相接的向量的转向关系。

CCW 的本质是向量叉积。给定两个向量,\(\vec{AB}\) 和 \(\vec{AC}\),它们的向量叉积公式为 \(cross = \vec{AB} \times \vec{AC} = (B_x - A_x) (C_y - A_y) - (B_y - A_y) (C_x - A_x)\),这个 \(cross\) 就是判断转向的依据:

  • 当 \(cross < 0\) 时,从点 \(A\) 到点 \(B\) 再到点 \(C\),路径呈逆时针方向旋转。
  • 当 \(cross = 0\) 时,\(A, B, C\) 三点共线。
  • 当 \(cross < 0\) 时,从点 \(A\) 到点 \(B\) 再到点 \(C\),路径呈顺时针方向旋转。

C++ 代码实现参考:

struct Point {double x, y;
};double ccw(Point a, Point b, Point c) {return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}

判断两线段是否相交

众所周知,对于两条线段 \(AB\) 和 \(CD\),如果 \(A\) 和 \(B\) 分别在 \(CD\) 的两侧,且 如果 \(C\) 和 \(D\) 分别在 \(AB\) 的两侧,则 \(AB\) 与 \(CD\) 相交。前者需满足 \(\mathrm{ccw}(A, B, C) \times \mathrm{ccw}(A, B, D) < 0\),即从向量 \(\vec{AB}\) 转向点 \(C\) 与点 \(D\) 的方向相反;类似地,后者需满足 \(\mathrm{ccw}(C, D, A) \times \mathrm{ccw}(C, D, B) < 0\)。

C++ 代码实现参考(需结合以上 ccw 的函数定义):

if (ccw(a, b, c) * ccw(a, b, d) < 0 && ccw(c, d, a) * ccw(c, d, b) < 0) {// 两条线段相交
}

相关题目参考题解

题目大意:给出 \(N\) 个点,两两连接这些点组成一个线段集合 \(S\),求 \(S\) 中不与其它任何线段相交的线段数量。

注意:以下题解是暴力做法,只能在原题中获得 25 分,AC 做法请参考官方题解。

#include <iostream>
#include <vector>
using namespace std;
#define int long long
#define endl '\n'
const int N = 1e3 + 10;
struct Point {int x, y;
} p[N];
struct Side {Point a, b;
};
vector<Side> s;
int n, ans;
int ccw(Point a, Point b, Point c) {return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y);
}signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n;for (int i = 1; i <= n; i++) {int x, y;cin >> x >> y;p[i] = {x, y};}for (int i = 1; i <= n - 1; i++) {for (int j = i + 1; j <= n; j++) {s.push_back({p[i], p[j]});}}for (int i = 0; i < s.size(); i++) {int suc = true;for (int j = 0; j < s.size(); j++) {Point a = s[i].a, b = s[i].b, c = s[j].a, d = s[j].b;if (ccw(a, b, c) * ccw(a, b, d) < 0 && ccw(c, d, a) * ccw(c, d, b) < 0) {suc = false;break;}}if (suc) {ans++;}}cout << ans << endl;return 0;
}

小结

CCW 算法只是计算几何庞大世界的沧海一粟,这一广阔的算法天地仍有很多地方值得我们探索。例如,若要在上文提到的题目中获得满分,必须要学习包括凸包在内的更高级的计算几何算法。路漫漫其修远兮,希望大家以十足的兴趣,自主探索计算几何的奇妙世界。

相关新闻

  • Robot Queries
  • 特殊的数字签名
  • 102302136 林伟杰 数据采集与融合作业1

最新新闻

  • [Windows]罗技G HUB(Logitech G HUB)旧版本下载地址汇总
  • 电瓶车托运不拆电池行吗?2026新规+省钱方案来了 - 快递物流资讯
  • 2026年北京发电机租赁、应急电源车租赁厂家名单及选购参考指南 - 海棠依旧大
  • 如何配置远程的ubuntu服务器以使在本地windows电脑上可以进行X11图形转发——ssh远程X11转发的配置
  • 电商平台XSS攻击实战防御:从前端到后端的双重安全防线
  • 合肥口碑最好的中专选哪家?综合实力优选合肥理工学校! - 教育为先

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号