POJ 1127 /// 判断线段与线段是否相交
题目大意:
给定n条线段
接下来n行是端点信息
接下来询问 a b 是否相交
若a与c相交 b与c相交 ,那么a与b就是相交的
先判断任两条线段是否相交 再用folyd
#include <cstdio> #include <cmath> #include <algorithm> #include <stdio.h> #include <string.h> using namespace std; const double eps = 1e-10; double add(double a,double b) { if(abs(a+b)<eps*(abs(a)+abs(b))) return 0; return a+b; } // 考虑误差 struct P { double x,y; P(){}; P(double _x,double _y):x(_x),y(_y){} P operator -(P p) { return P(add(x,-p.x),add(y,-p.y)); }; P operator +(P p) { return P(add(x,p.x),add(y,p.y)); }; P operator *(double d) { return P(x*d,y*d); }; double dot(P p) { return add(x*p.x,y*p.y); }; double det(P p) { return add(x*p.y,-y*p.x); }; }; // c在直线ab上 外积==0,c在ab两点之间 内积<=0 bool onSeg(P a,P b,P c) { return (a-c).det(b-c)==0 && (a-c).dot(b-c)<=0; } // 求两直线ab与cd交点 /* 设直线ab上点为 a+(b-a)t,t为变量 交点需满足在直线cd上 则(d-c)*(a+t(b-a)-c)=0(外积) 分解为加减式子 将t放在等号左边 其他放在右边 化简推导得t=(d-c)*(c-a)/(d-c)*(b-a) 则交点为a+(b-a)*((d-c)*(c-a)/(d-c)*(b-a)) */ P ins(P a,P b,P c,P d) { return a+(b-a)*((d-c).det(c-a)/(d-c).det(b-a)); } bool insSS(P a,P b,P c,P d) { if((a-b).det(c-d)==0) //平行 return onSeg(a,b,c) || onSeg(a,b,d) || onSeg(c,d,a) || onSeg(c,d,b); else { P t=ins(a,b,c,d); return onSeg(a,b,t) && onSeg(c,d,t); } } int main() { int n,x,y; bool G[20][20]; P p[20],q[20]; while(~scanf("%d",&n)) { if(n==0) break; for(int i=0;i<n;i++) scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y); memset(G,0,sizeof(G)); for(int i=0;i<n;i++) { G[i][i]=1; for(int j=0;j<i;j++) G[i][j]=G[j][i]=insSS(p[i],q[i],p[j],q[j]); } for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) G[j][k] |= G[j][i]&&G[i][k]; while(~scanf("%d%d",&x,&y)) { if(x+y==0) break; if(G[--x][--y]) printf("CONNECTED\n"); else printf("NOT CONNECTED\n"); } } return 0; }