分析&&题解:
给出N条线段,每条线段告诉你起始点和结束点,判断这N条线段构成多少条交点,不同线段交于一点可以被重复计算。这就非常简单了,直接模板过去。判断线段相交(包括端点):
double multiply(point sp, point ep, point op) //得到线段(sp-op)和线段(ep-op)的叉积
{
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
bool intersect(line u, line v) //判断线段u和线段v是否相交
{
return( (max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&& //排斥实验
(max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&&
(max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&&
(max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&&
(multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)>=0)&& //跨立实验
(multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0));
}
- AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
struct point
{
double x;
double y;
};
struct line
{
point s;
point e;
}lines[110];
point A1B1, B2B1, A2A1, B2A1;
double multiply(point sp,point ep,point op)
{
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
bool intersect(line u,line v)
{
return( (max(u.s.x,u.e.x)>=min(v.s.x,v.e.x))&& //排斥实验
(max(v.s.x,v.e.x)>=min(u.s.x,u.e.x))&&
(max(u.s.y,u.e.y)>=min(v.s.y,v.e.y))&&
(max(v.s.y,v.e.y)>=min(u.s.y,u.e.y))&&
(multiply(v.s,u.e,u.s)*multiply(u.e,v.e,u.s)>=0)&& //跨立实验
(multiply(u.s,v.e,v.s)*multiply(v.e,u.e,v.s)>=0));
}
int main()
{
int N;
while(cin >>N && N)
{
for(int i=0;i<N;i++)
{
cin >> lines[i].s.x>>lines[i].s.y >> lines[i].e.x >> lines[i].e.y;
}
int cnt = 0;
for(int i=0;i<N;i++)
{
for(int j=i+1;j<N;j++)
{
if( intersect(lines[i], lines[j]) )
{
cnt++;
}
}
}
cout << cnt << endl;
}
}