哈理工 1559 线段相交【计算几何】
2016-01-26 14:54
295 查看
线段相交 | ||||||
| ||||||
Description | ||||||
给定线段P1P2(P1和P2是线段的两端点,且不重合)、P3P4(P3和P4是线段的两端点,且不重合),判断P1P2和P3P4是否相交。P1P2和P3P4相交,即指存在一个点P,它既落在P1P2上又落在P3P4上(含线段的端点)。 | ||||||
Input | ||||||
输入数据有多组,第一行为测试数据的组数N,下面包括2N行,每组测试数据含2行,第一行为P1P2的坐标值,第二行为P3P4的坐标值,比如下面的数据 表示P1、P2、P3、P4的坐标分别为:P1(0,0),P2(1,1),P3(2,2),P4(3,3) | ||||||
Output | ||||||
判断每组数据中的线段P1P2和P3P4是否相交,如果相交输出YES,否则输出NO。每组数据输出占一行。 | ||||||
Sample Input | ||||||
2 0 0 1 1 2 2 3 3 0 0 2 0 0 0 1 3 | ||||||
Sample Output | ||||||
NO YES | ||||||
Hint | ||||||
两线段相交分为“规范相交”和“非规范相交”。 “规范相交”指的是两条线段恰有唯一一个不是端点的公共点;而如果一条线段的一个端点在另一条线段上,或者两条线段部分重合,则视为“非规范相交”,本题是“非规范相交”。 定义点坐标类型时需用double |
首先要知道,我们一定要先通过了快速排斥试验我们才能继续判断是否两条线相交,如果快速排斥试验都没能通过,那么这两条线是一定不会相交的。
//快速排斥试验 if(min(a.x,b.x)>max(c.x,d.x)||min(a.y,b.y)>max(c.y,d.y)||min(c.x,d.x)>max(a.x,b.x)||min(c.y,d.y)>max(a.y,b.y)) return false;接下来继续判断两条线是否相交:如果c,d两点在线段ab两端。并且a,b两点,在线段cd两端,那么就能说明两条直线相交。并且我们知道,向量叉乘可以判断一个线段在另一个线段的顺时针方向还是逆时针方向,如果cb和bd在ab的相反方向。也就是说向量叉乘的结果一个是正,一个是负。叉乘的值相乘如果是个负值,那就说明一定是cd在ab的两端了,同理,为了避免个别情况,也要判断一下ab在cd两端:
u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);//c.b.a//u的正负表示bc在ab的顺时针方向还是逆时针方向. v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);//d.b.a//同理 w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);//a.d.c z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);//b.d.c return (u*v<=0.00000001 && w*z<=0.00000001);
然后是完整的AC代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
struct dian
{
double x,y;
}a[100];
bool judge(dian a,dian b,dian c,dian d)
{
//快速排斥试验 if(min(a.x,b.x)>max(c.x,d.x)||min(a.y,b.y)>max(c.y,d.y)||min(c.x,d.x)>max(a.x,b.x)||min(c.y,d.y)>max(a.y,b.y)) return false;
double u,v,w,z;
u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);//c.b.a//u的正负表示bc在ab的顺时针方向还是逆时针方向. v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);//d.b.a//同理 w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);//a.d.c z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);//b.d.c return (u*v<=0.00000001 && w*z<=0.00000001);
}
int main()
{
int t;
cin>>t;
while(t--)
{
double aa,b,c,d,e,f,g,h;
cin>>aa>>b>>c>>d>>e>>f>>g>>h;
a[0].x=aa;
a[0].y=b;
a[1].x=c;
a[1].y=d;
a[2].x=e;
a[2].y=f;
a[3].x=g;
a[3].y=h;
if(judge(a[0],a[1],a[2],a[3]))
printf("YES\n");
else
printf("NO\n");
}
}
相关文章推荐
- CentOS:Error: Nothing to do
- 32.Which CREATE TABLE statement is valid?
- Android类参考---Fragment
- Android下各个按键对应的key code
- PHP CURL上传文件
- iOS最全的常用正则表达式大全
- 【198】Synergy - 鼠标键盘共享软件
- installshield 制作安装包中执行其他程序LaunchAppAndWait的简介
- python全局变量
- Tomcat Service
- YTU 2893: F--Mark的双薪
- android触碰事件
- ASP.NET使用WebMethod
- C# 采用Basic Auth传递Post或者GET 数据
- (转载)如何开通 CloudFront 和 Route 53 ?
- UI方面总结
- 使用SqlMapClient后sql的写法(待完善)
- JAVA程序中乱码处理
- JAVA程序中乱码处理
- JAVA程序中乱码处理