哈理工OJ 1579 又见线段相交【计算几何】
来源:互联网 发布:如何导出股票数据 编辑:程序博客网 时间:2024/06/05 11:48
又见线段相交Time Limit: 1000 MSMemory Limit: 10240 KTotal Submit: 81(39 users)Total Accepted: 41(37 users)Rating: Special Judge: NoDescription
给定线段P1P2(P1和P2是线段的两端点,且不重合)、P3P4(P3和P4是线段的两端点,且不重合),判断P1P2和P3P4是否相交。
P1P2和P3P4相交,即指仅存在一个点P,该交点不能是线段的端点。
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是否相交,如果相交输出交点坐标,输出用小数表示,精确到小数点后两位,否则输出NO。每组数据输出占一行。Sample Input3
0 0 1 1
2 2 3 3
0 0 2 0
0 0 1 3
0 0 1 1
0 1 1 0
Sample OutputNO
NO
(0.50,0.50)
Hint两线段相交分为“规范相交”和“非规范相交”。 “规范相交”指的是两条线段恰有唯一一个不是端点的公共点;而如果一条线段的一个端点在另一条线段上,或者两条线段部分重合,则视为“非规范相交”,本题是“规范相交”。 定义点坐标类型时需用double这里边比裸线段相交的题多了两个内容:
1.规范相交
2.计算相交的点的位子
相信大家计算相交点的位子是会的,这里就不重点说明了,这里说一下整体的思路,和规范相交的问题:
首先,无论是规范相交还是非规范相交,一旦是相交了,那么一定是通过了快速排斥试验以及跨立试验的、所以我们这里先判断两条线段是否相交、如果不相交、结束。
这里对应部分代码详解:
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);//如果u*v<=<span style="font-family: Arial, Helvetica, sans-serif;">0.00000001,那么说明点c,d在线段ab两端,同理,w*z也是一样<span style="white-space:pre"></span> }</span>然后就是判断这个相交是规范相交还是非规范相交,这里我们知道,如果三个点共线了,那么就说明不是规范相交、结束。而且我们还知道,三点叉乘==0的时候 ,说明三点共线了、这里是判断是否为规范相交的代码:
int segment(dian p1,dian p2,dian p3){ if((p3.x-p1.x)*(p2.y-p1.y)-(p2.x-p1.x)*(p3.y-p1.y)==0) return 1;//表示这就不是规范相交 else return 0;}最后上完整的AC代码:
#include<stdio.h>#include<string.h>#include<iostream>using namespace std;struct dian{ double x,y;}p[4];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 segment(dian p1,dian p2,dian p3){ if((p3.x-p1.x)*(p2.y-p1.y)-(p2.x-p1.x)*(p3.y-p1.y)==0) return 1; else return 0;}int main(){ int t; scanf("%d",&t); while(t--) { double a,b,c,d; double e,f,g,h; scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f,&g,&h); p[0].x=a; p[0].y=b; p[1].x=c; p[1].y=d; p[2].x=e; p[2].y=f; p[3].x=g; p[3].y=h; if(judge(p[0],p[1],p[2],p[3])) { if(segment(p[0],p[1],p[2])||segment(p[0],p[1],p[3])) { printf("NO\n"); } else { double k1=(p[1].y-p[0].y)/(p[1].x-p[0].x); double k2=(p[3].y-p[2].y)/(p[3].x-p[2].x); double b1=p[1].y-k1*p[1].x; double b2=p[3].y-k2*p[3].x; double x=(b2-b1)/(k1-k2); double y=k1*x+b1; printf("(%.2lf,%.2lf)\n",x,y); } } else { printf("NO\n"); } }}
0 0
- 哈理工OJ 1579 又见线段相交【计算几何】
- 哈理工OJ 1559 线段相交(计算几何)
- 哈理工 1559 线段相交【计算几何】
- 【计算几何】线段相交
- poj1039(计算几何)线段相交
- 【计算几何】判断线段相交
- 计算几何 线段相交 模板
- hrbust 哈理工oj 1729 Finding the Way【计算几何】
- {计算几何}怎样判断线段相交
- 计算几何,判两线段相交模板
- 计算几何之判断线段相交
- poj3304 计算几何 线段与直线相交
- HDU 1086 计算几何 判断线段相交
- 计算几何中的线段相交判断问题
- POJ 2318 TOYS 计算几何 线段相交
- 计算几何之两线段相交
- 计算几何--判断线段是否相交
- 计算几何:线段相交(迷宫寻宝)
- R语言-AHP层次分析法
- Redis java操作
- 并查集入门简略笔记 附HDU1232
- TreeSet集合介绍
- TokuDB · Cachetable 的工作线程和线程池
- 哈理工OJ 1579 又见线段相交【计算几何】
- MongoDB使用教程系列文章--Driver原理(初始化)
- Hyper-V中的“Network adapter “和“Legacy Network adapter”之间的区别
- HttpClient_4 用法(HC3-->HC4必看)
- [故障及解决]window下,mysql的root密码的修改
- 物理备份死锁分析
- MongoDB使用教程系列文章--开篇
- 状态空间模型
- bzoj 1857 传送带