TZOJ 3348: 线段相交Ⅲ

题目链接 :线段相交Ⅲ

        这题就是数论题目,考察了数学,老实说我不是很会解释这个。

        首先要能证明两个线段相交,这个要用到快速排斥实验。很简单知道线段的左端点大于另一线段右端点,或者线段下端点大于另一线段上端点,这俩线段必不相交。

        之后用到跨立实验,通过叉积来判断是否线段之间相互位置吗,叉积=0,代表线段端点在另一线段上,<0说明线段两端点在另一线段两侧,>0说明在同一侧。

        最后是要求交点。这个要是人来判断就简单多了,画图什么就行,可惜是机器,那就需要用到数学,就是定比分点。不是很会解释,定义如下:

和两点间的中点公式一样,定比分点公式是一种给出中点坐标的公式。定比分点应该理解为:“固定比点的坐标公式”,中点公式是他的一种特殊情况。我们可以用它寻找三角形的内心、质心和外心。它是在一个线段中按照固定比例将线段分为两部分。就是一个点将线段截成两段。该公式可以告知任何一个固定比例的点在坐标系的位置。

         然后下面是代码,只能说我数学不太行。

#include<bits/stdc++.h>
#define ll long long
#define N 500005
#define M 105
#define debug cout<<"~~debug "
#define rc p<<1|1
#define lc p<<1
#define PII pair<long long,long long>
#define pb push_back
#define Inf 0x3f3f3f3f
//neuro-sama
const ll mod = 1e9+7;
using namespace std;
inline int read()
{
	char c=getchar();int f=1,x=0;
	while(c>'9'||c<'0'){ if(c=='-') f=-f;c=getchar();}
	while(c<='9'&&c>='0'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
	return f*x;
}
struct node{
	double x;
	double y;	
};
typedef struct node node;
int n,T,m,k;
double cross(node a,node b,node c){
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int judge(node a,node b,node c,node d){//快速排斥实验
	if(max(a.x,b.x)<min(c.x,d.x)) return 1;
	else if(max(a.y,b.y)<min(c.y,d.y)) return 1;
	else if(max(c.x,d.x)<min(a.x,b.x)) return 1;
	else if(max(c.y,d.y)<min(a.y,b.y)) return 1;
	return 0;
}
void solve()
{
	node a,b,c,d;
	cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y;
	if(judge(a,b,c,d)){
		cout<<"NO\n";
		return;
	}
	double x=cross(a,b,c);
	double xx=cross(a,b,d);
	double y=cross(c,d,a);
	double yy=cross(c,d,b);
	if(x*xx>0||y*yy>0){
		cout<<"NO"<<endl;
		return;
	}
	if(x*xx==0||y*yy==0){
		cout<<"YES"<<endl;
		return;
	}
	double s=fabs(x)/fabs(xx);
	printf("YES (%.3lf %.3lf)\n",(c.x+s*d.x)/(1+s),(c.y+s*d.y)/(1+s));
}
int main()
{
//	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	T=1;
	cin>>T;
	while(T--)
	{
		solve();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值