1 快速排斥试验
设以线段 P1P2 为对角线的矩形为R,
设以线段 Q1Q2为对角线的矩形为T,
如果R和T不相交,显然两线段不会相交。
2 跨立试验
如果两线段相交,则两线段必然相互跨立对方。
若P1P2跨立Q1Q2 ,则矢量( P1- Q1)
和(P2-Q1)位于矢量( Q2-Q1)的两侧,
即(P1- Q1)×(Q2 -Q1) * (P2 - Q1)×( Q2 - Q1 ) > 0。
上式可改写成(P1-Q1)×(Q2 -Q1) * (Q2 - Q1)×(P2 -Q1) > 0。
当(P1 -Q1)×(Q2 -Q1)=0 时,说明( P1 - Q1)和(Q2 - Q1)共线,
但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;
同理,(Q2 -Q1)×(P2 -Q1)=0 说明 P2 一定在线段 Q1Q2上。
所以判断P1P2跨立Q1Q2的依据是:
( P1 - Q1 )×(Q2 - Q1) * (Q2 - Q1)×( P2 -Q1) >= 0。
同理判断Q1Q2跨立P1P2的依据是:
( Q1 - P1 )×( P2 - P1) * ( P2 - P1)×(Q2 - P1) >= 0。
X:为叉积 叉积的计算公式为: P1 X P2 = x1y2 - x2y1;
----以下是代码:
#include < string >
using namespace std;
struct Point
... {
double x;
double y;
} ;
struct segmemt
... {
Point s;
Point t;
} ;
double MAX( double a, double b)
... {
if(a>b)return a;
return b;
}
double MIN( double a, double b)
... {
if(a<b)return a;
return b;
}
// 判断p在不在ps---pe的顺时针或逆时针
/**/ /* m = (pe-ps) X (p-ps) m>0 逆时针 m==0 3点在同一直线 m<0 顺时针 */
double mulpti(Point ps , Point pe , Point p)
... {
double m;
m=(pe.x-ps.x)*(p.y-ps.y)-(p.x-ps.x)*(pe.y-ps.y);
return m;
}
bool inser(Point p1, Point p2 , Point p3, Point p4)
... {
if(MAX(p1.x,p2.x)>=MIN(p3.x,p4.x) &&
MAX(p3.x,p4.x)>=MIN(p1.x,p2.x) &&
MAX(p1.y,p2.y)>=MIN(p3.y,p4.y) &&
MAX(p3.y,p4.y)>=MIN(p1.y,p2.y) &&
mulpti(p1,p2,p3)*mulpti(p1,p2,p4)<=0 &&
mulpti(p3,p4,p1)*mulpti(p3,p4,p2)<=0)
return true;
else
return false;
}
int main()
... {
int n,i,j;
bool flag;
segmemt list[2000];
while(cin>>n)
...{
flag = true;
for(i=0;i<n;i++)
...{
cin>>list[i].s.x>>list[i].s.y;
cin>>list[i].t.x>>list[i].t.y;
}
if(n>1)
...{
for(i=0;i<n-1;i++)
...{
for(j=i+1;j<n;j++)
...{
if(inser(list[i].s,list[i].t,list[j].s,list[j].t))
...{
flag = false;
break;
}
}
if(flag == false)
break;
}
}
if(flag)
cout<<"ok!"<<endl;
else
cout<<"burned!"<<endl;
}
return 0;
}