POJ1127_Jack Straws_叉积::判断两线段是否相交

题意

给出 n 条线段端点的坐标,然后给出若干组询问。每组询问包含两个数字,输出这两个数字代表的线段是否联通。线段从 1 到 n 编号。通过联通的线段间接连在一起的线段,认为这两条线段也是联通的。

思路

判断两线段是否相交,首先求出两线段所在直线的交点,然后看这个交点是否在两条线段上。如果在,则两条线段相交。
可以利用坐标求两直线的方程然后进行运算,但运用向量的内积和外积更简单。

内积与外积

内积 = x1 * y1 + x2 * y2 , 外积 = x1 * y 2 - x2 * y1 。
外积的公式可以借助行列式来记忆,对于三维坐标也适用。

判断点是否在线段上

1.利用外积判断点q是否在p1 - p2线段所在的直线上

线段所在直线的方向向量可以表示成 p1 - p2 。
点在直线上,则有 (p1 - q) X (p2 - q) = 0

2.利用内积进一步判断点是否在线段上

点在直线上的基础上,进一步判断点是否落在线段内,即线段的两端点之间。
直线上的点在线段上,则有 (p1 - q) * (p2 - q) <= 0

利用外积求两直线(p1 - p2, q1 - q2)的交点

设一个变量 t,则直线 p1 - p2 上的点可以表示成 p1 + t (p1 - p2) 。又该点也在直线 q1 - q2 上,所有有 (q2 - q1) X (p1 + t(p1 - p2) - p1) = 0 。解出 t 的表达式后代入 p1 + t(p1 - p2) 即得到了交点的向量即坐标:
p1 + (p2 - p1) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1));

特殊情况

如果两条线段所在直线的方向向量平行,这两条线段依然有可能相交。对于这种情况,若只需要判断线段的端点即可。
若两条线段中,至少一条线段的至少一个端点在另一条线段上,则这两条线段相交。

算法过程

1.首先判断两条线段所在直线的方向向量是否平行,若平行,则按照特殊情况处理
2.对于不平行的情况,首先利用公式求出两线段所在直线的交点,然后判断这个交点是否在两条线段上。如果在,则两条线段相交。
3.最后,利用floyd算法求出线段联通关系的图即可。

注意

1.几何问题一定要注意特殊情况的处理

具体分析可见《挑战程序设计竞赛 253 页》

2.计算误差问题

1.设置 eps,一般为 1e-10 。
a < 0 == a < -eps
a <= 0 == a < eps
a = 0 == abs(a) < eps
2.注意平方运算会使误差快速变大
3.考虑误差

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值