问题 C: 线段交

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态] [命题人:]

题目描述

给定N个线段。求有交点的线段对数。
保证没有两条线段共线

 

输入

一行一个整数N,表示线段的个数
第2~N+1行,每行四个实数,x1,y1,x2,y2,表示线段的两个端点(x1,y1)和(x2,y2)

 

输出

一行一个整数,表示交点的个数。

 

样例输入

复制样例数据

3
0.00 0.00 1.00 1.00
0.00 1.00 1.00 0.00
0.00 0.00 1.00 0.00

样例输出

3

 

提示

(0,0)(1,1)和(0,1)(1,0)有交点
(0,0)(1,1)和(0,0)(1,0)有交点
(0,1)(1,0)和(0,0)(1,0)有交点

对于100%的数据,N≤100
点的坐标范围(−10000,10000)

题解:模板题!

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const double eps = 1e-10;
struct point{
    double x, y;
};
struct Line{
    point l;
    point r;
};
double min(double a, double b){
    return a < b ? a : b;
}
 
double max(double a, double b){
    return a > b ? a : b;
}
 
bool inter(point a, point b, point c, point d){
    if (min(a.x, b.x) > max(c.x, d.x) || min(a.y, b.y) > max(c.y, d.y) || min(c.x, d.x) > max(a.x, b.x) || min(c.y, d.y) > max(a.y, b.y)){
        return 0;
    }
    double h, i, j, k;
    h = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    i = (b.x - a.x) * (d.y - a.y) - (b.y - a.y) * (d.x - a.x);
    j = (d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x);
    k = (d.x - c.x) * (b.y - c.y) - (d.y - c.y) * (b.x - c.x);
    return h * i <= eps && j * k <= eps;
}
int main(){
    int n;
    Line line[110];
    while(cin>>n&&n){
        for(int i=1;i<=n;i++){
            cin>>line[i].l.x>>line[i].l.y>>line[i].r.x>>line[i].r.y;
        }
        int cnt=0;
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(inter(line[i].l,line[i].r,line[j].l,line[j].r))
                cnt++;
            }
        }
        cout<<cnt<<endl;
    }
}