O(n2)的暴力居然能过。。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 200005 #define db double const db eps=1e-6; int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;} int cmp(db k1,db k2){return sign(k1-k2);} struct point{ db x,y; point(){} point(db x,db y):x(x),y(y){} point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} point operator * (db k1) const{return (point){x*k1,y*k1};} point operator / (db k1) const{return (point){x/k1,y/k1};} }; struct line{ point p[2]; }; db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} int intersect(db l1,db r1,db l2,db r2){//跨立实验 if(l1>r1)swap(l1,r1);if(l2>r2)swap(l2,r2); return cmp(r1,l2)!=-1 && cmp(r2,l1)!=-1; } int checkSS(point k1,point k2,point k3,point k4){ return intersect(k1.x,k2.x,k3.x,k4.x) && intersect(k1.y,k2.y,k3.y,k4.y) && sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0 && sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0; } point p[N]; line l[N]; int n,vis[N],totp; int main(){ while(scanf("%d",&n) && n){ memset(vis,0,sizeof vis); for(int i=1;i<=n;i++){ point k1,k2; scanf("%lf%lf",&k1.x,&k1.y); scanf("%lf%lf",&k2.x,&k2.y); p[++totp]=k1;p[++totp]=k2; l[i].p[0]=k1;l[i].p[1]=k2; } for(int i=1;i<=n;i++){ int flag=0; for(int j=i+1;j<=n;j++) if(checkSS(l[i].p[0],l[i].p[1],l[j].p[0],l[j].p[1])){ flag=1;break; } if(!flag)vis[i]=1; } int flag=0; cout<<"Top sticks: "; for(int i=1;i<=n;i++)if(vis[i]){ if(flag==0){ cout<<i; flag=1; } else { cout<<", "<<i; } } puts("."); } }