poj3304 计算几何 线段与直线相交

时间:2023-01-09 22:10:14

题意:给定n条线段,确定是否存在一条直线,使得这n条线段在这条直线上的射影具有公共点

可将问题转化为是否存在一条直线经过所有的线段,证明见依然的博客:http://blog.sina.com.cn/s/blog_6635898a0100n2lv.html


#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

const double eps = 1e-8;
const int maxn = 111;

int n;

struct Point {
    double x, y;
};

struct Line {
    Point a, b;
} line[maxn];

double Multi(Point p1, Point p2, Point p0) {
    return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}

bool Check(Point a, Point b) {
    if (fabs(a.x-b.x) < eps && fabs(a.y-b.y) < eps) return false;
    for (int i = 0; i < n; i++)
        if (Multi(line[i].a, b, a) * Multi(line[i].b, b, a) > eps) return false;
    return true;
}

int main()
{
    int t, i, j;
    bool flag;

    scanf ("%d", &t);
    while (t--) {
        scanf ("%d", &n);
        for (i = 0; i < n; i++)
            scanf ("%lf%lf%lf%lf", &line[i].a.x, &line[i].a.y, &line[i].b.x, &line[i].b.y);
        flag = false;
        if (n < 3) flag = true;
        for (i = 0; i < n && !flag; i++) {
            if (Check(line[i].a, line[i].b)) flag = true;
            for (j = i + 1; j < n && !flag; j++) {
                if (Check(line[i].a, line[j].a) ||
                    Check(line[i].a, line[j].b) ||
                    Check(line[i].b, line[j].a) ||
                    Check(line[i].b, line[j].b))
                    flag = true;
            }
        }
        if (flag) printf ("Yes!\n");
        else printf ("No!\n");
    }
    return 0;
}