线段相交判断
/* 链表维护 n^2算法? */ #include<cstdio> #include<algorithm> using namespace std; const int N=1e5+50; const double eps=1e-9; struct Point { double x,y; Point(){} Point(double _x,double _y){x=_x,y=_y;} }; Point operator - (Point A,Point B) {return Point(A.x-B.x,A.y-B.y);} double operator ^ (Point A,Point B) {return A.x*B.y-A.y*B.x;} double cross(Point a,Point b,Point c) {return (a-c)^(b-c);} struct Line { Point s,e; Line(){} Line(Point _s,Point _e){s=_s,e=_e;} }L[N]; int nxt[N],pre[N],n,sta[N],top; void cut(int x) {nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x];} bool check(Line l1,Line l2) // 线段相交的判断。。有点累赘 { if(min(l2.s.x,l2.e.x)>max(l1.s.x,l1.e.x)) return 0; if(min(l2.s.y,l2.e.y)>max(l1.s.y,l1.e.y)) return 0; if(min(l1.s.x,l1.e.x)>max(l2.s.x,l2.e.x)) return 0; if(min(l1.s.y,l1.e.y)>max(l2.s.y,l2.e.y)) return 0; // 相当于 左边线段的最大值都要比右边线段的最小值小 // 或者是 上面线段的最小值比下面线段的最大值要大 一定没有交点 if(cross(l1.s,l2.e,l2.s)*cross(l1.e,l2.e,l2.s)>eps) return 0; if(cross(l2.s,l1.e,l1.s)*cross(l2.e,l1.e,l1.s)>eps) return 0; // 两种 跨立实验 return 1; //排除不相交的情况 剩下就相交了 } int main() { while(scanf("%d",&n)&&n) { for(int i=1;i<=n;i++) { double x,y;Point a,b; scanf("%lf%lf",&x,&y);a=Point(x,y); scanf("%lf%lf",&x,&y);b=Point(x,y); L[i]=Line(a,b); nxt[i]=i+1; pre[i]=i-1; } nxt[0]=1; pre[n+1]=n; for(int i=1;i<=n;i++) for(int j=nxt[0];j<i;j=nxt[j]) if(check(L[i],L[j])) cut(j); top=0; for(int i=nxt[0];i<=n;i=nxt[i]) sta[++top]=i; printf("Top sticks: %d",sta[1]); for(int i=2;i<=top;i++) printf(", %d",sta[i]);puts("."); } return 0; }