HDU

给你 n 条线段,计算这 n 条线段总共的交点数目。

 

几何线段相交的裸题。

快速排斥实验 +  跨立实验,N^2 两两判断就可以。

关于上述判定线段相交的方法可以去百度资料,在此不再赘述。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
#define maxn 200 + 100

struct Point
{
        double x, y;
        Point (double xx = 0, double yy = 0) : x(xx), y(yy) {}
        Point operator - (const Point& a)
        {
                return Point(x-a.x, y-a.y);
        }
};

Point a1[maxn], a2[maxn];

bool quick_exclude(Point a1, Point a2, Point b1, Point b2)//快速排斥实验
{
        if (max(a1.x, a2.x) < min(b1.x, b2.x)) return false;
        if (max(b1.x, b2.x) < min(a1.x, a2.x)) return false;
        if (max(a1.y, a2.y) < min(b1.y, b2.y)) return false;
        if (max(b1.y, b2.y) < min(a1.y, a2.y)) return false;
        return true;
}

double cross(Point a, Point b) //返回两个共面向量叉乘的z值
{
        return a.x * b.y - a.y * b.x;
}

bool walk_across(Point a1, Point a2, Point b1, Point b2)//跨立实验
{
        if (cross(a1-b1, b2-b1) * cross(a2-b1, b2-b1) > 0) return false;
        if (cross(b1-a1, a2-a1) * cross(b2-a1, a2-a1) > 0) return false;
        return true;
}

int main()
{
        int n;
        while(~scanf("%d", &n) && n)
        {
                for (int i = 1; i <= n; i++)
                        scanf("%lf%lf%lf%lf", &a1[i].x, &a1[i].y, &a2[i].x, &a2[i].y);

                int ans = 0;

                for (int i = 1; i <= n; i++)
                        for (int j = i+1; j <= n; j++)
                        {
                                if (quick_exclude(a1[i], a2[i], a1[j], a2[j])
                                    && walk_across(a1[i], a2[i], a1[j], a2[j]))
                                        ans++;
                        }

                printf("%d
", ans);
        }

}
原文地址:https://www.cnblogs.com/ruthank/p/9493535.html