C. Line-line Intersection

C. Line-line Intersection传送门

在这里插入图片描述
在这里插入图片描述

本题的关键在于重合直线的巧妙计数;

#include<bits/stdc++.h>
#define LL long long
using namespace std;

map<pair<LL,LL> , LL> mp;
map<pair<pair<LL,LL>,LL>,LL> mmp;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		mp.clear() ;
		mmp.clear() ;
		LL sum=0;
		int n;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			LL a,b,c,d;
			scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
			LL gcd = __gcd(a-c,b-d);
			LL A = ++mp[{(b-d)/gcd,(a-c)/gcd}];
			LL B = ++mmp[{{(b-d)/gcd,(a-c)/gcd},(b-d)/gcd*a+(a-c)/gcd*b}];
			sum+=i+B-A;
		}
		cout<<sum<<endl;
	}
	return 0;
 } 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线段的交点和点到线的距离可以使用向量运算来实现。 求两条线的交点可以按照以下步骤进行: 1. 计算出每条线段的方向向量 d1 和 d2。 2. 计算出每条线段的起点 p1 和 p2。 3. 计算出向量 p2-p1 在 d1 和 d2 上的投影长度 t1 和 t2。 4. 如果 t1 和 t2 都为 0,说明两条线段重合,交点可以是任意一个端点。 5. 如果 t1 和 t2 都不为 0,说明两条线段相交,交点为 p1+t1*d1 或 p2+t2*d2。 6. 如果 t1 和 t2 中有一个为 0,说明两条线段平行或重合,无交点。 7. 如果 t1 和 t2 都为 0,说明两条线段共线,但不重合,无交点。 代码如下: ``` public Point getIntersection(Line line) { Point p1 = this.getStartPoint(); Point p2 = this.getEndPoint(); Point q1 = line.getStartPoint(); Point q2 = line.getEndPoint(); Vector d1 = new Vector(p2.x - p1.x, p2.y - p1.y); Vector d2 = new Vector(q2.x - q1.x, q2.y - q1.y); double cross = Vector.crossProduct(d1, d2); if (Math.abs(cross) < 1e-6) { // Lines are parallel or colinear return null; } Vector w = new Vector(p1.x - q1.x, p1.y - q1.y); double t1 = Vector.crossProduct(d2, w) / cross; double t2 = Vector.crossProduct(d1, w) / cross; if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1) { // Intersection point is outside the segments return null; } Point intersection = new Point(p1.x + t1 * d1.x, p1.y + t1 * d1.y); return intersection; } ``` 求点到线的距离也可以使用向量运算来实现。 设点为 P,线段为 AB,则点到线的距离为线段 AC 的长度,其中 C 是点 P 在直线 AB 上的投影点。可以按照以下步骤进行计算: 1. 计算出向量 AB 和 AP。 2. 计算出向量 AP 在 AB 上的投影长度 t。 3. 如果 t 小于 0,则点 P 在线段 A 的左侧,距离为 AP 的长度。 4. 如果 t 大于 1,则点 P 在线段 B 的右侧,距离为 BP 的长度。 5. 否则,点 P 在线段 AB 内部,距离为 AC 的长度,其中 C 为线段 AB 上距离点 P 最近的点。 代码如下: ``` public double distanceTo(Point point) { Point p1 = this.getStartPoint(); Point p2 = this.getEndPoint(); Vector ab = new Vector(p2.x - p1.x, p2.y - p1.y); Vector ap = new Vector(point.x - p1.x, point.y - p1.y); double t = Vector.dotProduct(ab, ap) / Vector.dotProduct(ab, ab); if (t < 0) { // Point is outside the line segment, closest point is A return Point.distance(point, p1); } else if (t > 1) { // Point is outside the line segment, closest point is B return Point.distance(point, p2); } else { // Point is inside the line segment, closest point is C Point c = new Point(p1.x + t * ab.x, p1.y + t * ab.y); return Point.distance(point, c); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值