ACM暑假训练时做的题目,一个模板题判断两条线段是否相交,涉及到数学里的向量叉乘,判断条件如下:
1.两条线段相交,一条线段的左右端点在分别另一条线段的左右两侧,向量积表示。
2.特殊情况,一条线段的端点在另一条线段上,向量积是0,要进行特判。
就是代码丑了点O__O "…
#include
#include
using namespace std;
struct node {
double x1,y1,x2,y2;
}c[102];
int t;
int cross(node a,node b);
int on(double a,double b,double c,double d,double e,double f);
int main()
{
while(~scanf("%d",&t)&&t){
for(int i = 0;i < t;i++)
scanf("%lf%lf%lf%lf",&c[i].x1,&c[i].y1,&c[i].x2,&c[i].y2);
long long int sum = 0;
for(int i = 0;i < t;i++){
for(int j = i+1;j < t;j++){
if(cross(c[i],c[j]))
sum++;
}
}
printf("%I64d\n",sum);
}
return 0;
}
int cross(node a,node b)
{
node r,t,s,x,y,z;
//以线段a的(x1,y1)作为起点
r.x1 = b.x1-a.x1;
r.y1 = b.y1-a.y1;
t.x1 = a.x2-a.x1;
t.y1 = a.y2-a.y1;
s.x1 = b.x2-a.x1;
s.y1 = b.y2-a.y1;
//以线段b的(x1,y1)作为起点
x.x1 = a.x1-b.x1;
x.y1 = a.y1-b.y1;
y.x1 = b.x2-b.x1;
y.y1 = b.y2-b.y1;
z.x1 = a.x2-b.x1;
z.y1 = a.y2-b.y1;
//向量积运算
if(((r.x1*t.y1-t.x1*r.y1<0&&s.x1*t.y1-t.x1*s.y1>0)||(r.x1*t.y1-t.x1*r.y1>0&&s.x1*t.y1-t.x1*s.y1<0))
&&((x.x1*y.y1-y.x1*x.y1<0&&z.x1*y.y1-y.x1*z.y1>0)||(x.x1*y.y1-y.x1*x.y1>0&&z.x1*y.y1-y.x1*z.y1<0)))
return 1;
//四个特判
else if(r.x1*t.y1-t.x1*r.y1==0&&on(a.x1,a.y1,a.x2,a.y2,b.x1,b.y1))
return 1;
else if(s.x1*t.y1-t.x1*s.y1==0&&on(a.x1,a.y1,a.x2,a.y2,b.x2,b.y2))
return 1;
else if(x.x1*y.y1-y.x1*x.y1==0&&on(b.x1,b.y1,b.x2,b.y2,a.x1,a.y1))
return 1;
else if(z.x1*y.y1-y.x1*z.y1==0&&on(b.x1,b.y1,b.x2,b.y2,a.x2,a.y2))
return 1;
return 0;
}
int on(double a,double b,double c,double d,double e,double f)
{
if(min(a,c)<=e&&e<=max(a,c)&&min(b,d)<=f&&f<=max(b,d))
return 1;
return 0;
}