题意:给定n条线段(n≤100),求有多少个交点(若有多于两条线段交于一点,应重复计数(即可以视为任意两条线段不交于同一点))。
题解:判定线段相交的裸题。只需要枚举任意两条线段是否相交即可。(方法为判断线段AB的端点A,B是否在线段CD两侧,且C,D在线段AB两侧。注意特判一个端点在另一条线段上的情况。)
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #define eps 1e-15 8 using namespace std; 9 int n,t,ans; 10 struct vec{ 11 double x,y; 12 }; 13 struct node{ 14 vec a,b; 15 }e[110]; 16 double che(vec a,vec b){ 17 return a.x*b.y-a.y*b.x; 18 } 19 double ab(vec a){ 20 return a.x*a.x+a.y*a.y; 21 } 22 vec miu(vec a,vec b){ 23 return (vec){a.x-b.x,a.y-b.y}; 24 } 25 bool on(node a,node b){ 26 double x=ab(miu(b.a,a.a)),y=ab(miu(a.b,b.a)),z=ab(miu(a.b,a.a)); 27 if(x+y==z) return true; 28 x=ab(miu(b.b,a.a));y=ab(miu(a.b,b.b)); 29 if(x+y==z) return true; 30 return false; 31 } 32 bool pan(node a,node b){ 33 vec aa=miu(a.b,a.a); 34 double x=che(miu(a.b,a.a),miu(b.a,a.a))*che(miu(a.b,a.a),miu(b.b,a.a)); 35 double y=che(miu(b.b,b.a),miu(a.a,b.a))*che(miu(b.b,b.a),miu(a.b,b.a)); 36 if(x<0 && y<0) return true; 37 if(on(a,b)) return true; 38 return false; 39 } 40 int main(){ 41 int i,j,k,l; 42 scanf("%d",&n); 43 while(n!=0){ 44 ans=0;memset(e,0,sizeof(e)); 45 for(i=1;i<=n;++i){ 46 scanf("%lf%lf%lf%lf",&e[i].a.x,&e[i].a.y,&e[i].b.x,&e[i].b.y); 47 for(j=1;j<i;++j){ 48 if(pan(e[j],e[i])) ans++; 49 } 50 } 51 printf("%d\n",ans); 52 scanf("%d",&n); 53 } 54 return 0; 55 }