题意不说,已经很明了,这里主要是用了acmppt里面的那个拐向方法判断两条线段是否相交;
先写点基本知识:
1. 两下向量p1 ,p2 它们的叉乘(不是点乘):
p1Xp2 = x1*y2-x2*y1 = -p2Xp1;
如果:
p1Xp2 >0 :表示p2在p1的顺时针方向;
p1Xp2 < 0:表示p2在p1的逆时针方向;
p1Xp2 = 0: 表示p1 与 p2共线,方向不定;
2.判断折线的拐向:
再看图:
我们可用判断折线p2 p1 p3 和 p2 p1 p4的拐向从而知道 点 p4与p3是否分别位于线段p1p2的两边; 同理可以知道点p1 p2 是否在线段p3p4的两边;
如果都成立则线段相交;否则如图当p1,p4,p2共线,只要判断p4是否在点p1 与p2之间就可以了,这很容易;
判断拐向的代码(判断点c在线段ab的那一边):
double direction(cor& a,cor& b,cor& c){//以判断折线拐向的方法判断C点在线段s1的那边
double x0 = b.x-a.x;
double y0 = b.y-a.y;
double x1 = c.x-a.x;
double y1 = c.y-a.y;
return x0*y1-x1*y0;
}
共线时的情况:
bool on_segment(cor& a,cor& b,cor& c){//cout <<a.x <<' '<<a.y << ' '<<b.x <<' ' <<b.y <<' ' <<c.x <<' ' <<c.y <<endl;
return ((min(a.x,b.x) <= c.x && c.x <= max(a.x,b.x))
&& (min(a.y,a.y) <= c.y,c.y <= max(a.y,b.y)));
}
原代码:
#include<iostream>
#include<cmath>
#define N 100
using namespace std;
struct cor{
double x,y;
};
struct elem{
cor a;
cor b;
};
double direction(cor& a,cor& b,cor& c){//以判断折线拐向的方法判断C点在线段s1的那边
double x0 = b.x-a.x;
double y0 = b.y-a.y;
double x1 = c.x-a.x;
double y1 = c.y-a.y;
return x0*y1-x1*y0;
}
bool on_segment(cor& a,cor& b,cor& c){//cout <<a.x <<' '<<a.y << ' '<<b.x <<' ' <<b.y <<' ' <<c.x <<' ' <<c.y <<endl;
return ((min(a.x,b.x) <= c.x && c.x <= max(a.x,b.x))
&& (min(a.y,a.y) <= c.y,c.y <= max(a.y,b.y)));
}
bool judge(elem& s1,elem& s2){
double d1 = direction(s1.a,s1.b,s2.b);
double d2 = direction(s1.a,s1.b,s2.a);
double d3 = direction(s2.a,s2.b,s1.a);
double d4 = direction(s2.a,s2.b,s1.b);
if((d1*d2 < 0) && (d3*d4 < 0))
return true;
else if(!d1 && on_segment(s1.a,s1.b,s2.b))
return true;
else if(!d2 && on_segment(s1.a,s1.b,s2.a))
return true;
else if(!d3 && on_segment(s2.a,s2.b,s1.a))
return true;
else if(!d4 && on_segment(s2.a,s2.b,s1.b))
return true;
else
return false;
}
int main()
{
int nLines;
int count;
elem seg[N];
while(cin >>nLines && nLines){
count = 0;
for(int i = 0; i < nLines;i++){
cin >>seg[i].a.x >>seg[i].a.y >>seg[i].b.x >>seg[i].b.y;
}
for(int i = 0; i < nLines;i++){
for(int j = i+1; j < nLines;j++){
if(judge(seg[i],seg[j]))
count++;
}
}
cout <<count <<endl;
}
return 0;
}