3348: 线段相交Ⅲ 时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte 总提交: 388 测试通过:167 描述 线段相交有两种情形:一种是“规范相交”,另一种是“非规范相交”。规范相交是指两条线段恰有唯一一个不是端点的公共点。即如果一条线段的端点在另一条线段上则不视为相交。如果两条线段有部分重合,也不视为相交。而非规范相交则把以上两种情况都视为相交。如下图所示: 规范相交认为a,b两种情况都是不相交的,而非规范相交认为a,b两种情况都是相交的。 本题要求判断两条线段是否相交。如果是规范相交则输出YES,并输出交点坐标,如果是非规范相交则只需输出YES,如果不相交则输出NO。 输入 输入有多组数据,T表示输入数据的组数。每组测试数据有两行第一行输入一条线段的两个端点的坐标,第二行输入另一个线段的两个端点的坐标。 输出 对于每组测试数据,输出一行。如果是规范相交则输出YES,并输出交点坐标(小数点后面保留3位),如果是非规范相交则只需输出YES,如果不相交则输出NO。 样例输入 4 0 0 1 1 0 1 1 0 0 0 2 2 2 2 3 3 0 0 2 2 1.5 1.5 3 3 0 0 1 1 2 2 3 3 样例输出 YES (0.500,0.500) YES YES NO 首先判断两直线 1.快速排斥实验 2.叉乘 然后交点公式 x=x1+k*(x2-x1); y=y1+k*(y2-y1); k=lsl1(x1,y1,x2,y2,x3,y3,x4,y4); ac代码 #include<bits/stdc++.h> using namespace std; double lsl1(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4) { double k=((x3-x1)*(y4-y3)-(x4-x3)*(y3-y1))/((x2-x1)*(y4-y3)-(x4-x3)*(y2-y1)); return k; } int paichi(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4) { if(min(x1,x2)>max(x3,x4)||min(x3,x4)>max(x1,x2)||min(y1,y2)>max(y3,y4)||min(y3,y4)>max(y1,y2)) return 0; double a,b,c,d; a=(x2-x1)*(y3-y1)-(y2-y1)*(x3-x1); b=(x2-x1)*(y4-y1)-(y2-y1)*(x4-x1); c=(x4-x3)*(y1-y3)-(y4-y3)*(x1-x3); d=(x4-x3)*(y2-y3)-(y4-y3)*(x2-x3); if(a*b<0&&c*d<0) return 1; else if(a*b<=0&&c*d<=0) return 2; return 0; } void lsl() { double x1,y1,x2,y2,x3,y3,x4,y4; cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4; int f=paichi(x1,y1,x2,y2,x3,y3,x4,y4); if(f) { if(f==1) { double k=lsl1(x1,y1,x2,y2,x3,y3,x4,y4); double x=x1+k*(x2-x1); double y=y1+k*(y2-y1); printf("YES (%.3lf,%.3lf)\n",x,y); } else cout<<"YES\n"; } else cout<<"NO\n"; } int main() { int t; cin>>t; while(t--) { lsl(); } } |