Segments

题目大意:给出一些线段,然后判断这些线段的投影是否有可能存在一个公共点。
 
分析:如果这些线段的投影存在一个公共点,那么过这个公共点作垂线一定与所有的直线都想交,于是题目转化成是否存在一个直线可以经过所有的线段,考虑线段并不多,所以可以枚举任意两点当作直线......
 
代码如下:
=============================================================================================================================
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;

const int MAXN = 1007;
const double ESP = 1e-8;

struct Point
{
    double x, y;

    Point(double x=0, double y=0):x(x), y(y){}
    Point operator + (const Point &tmp) const{
        return Point(x+tmp.x, y+tmp.y);
    }
    Point operator - (const Point &tmp) const{
        return Point(x-tmp.x, y-tmp.y);
    }
    bool operator ==(const Point &tmp) const{
        return (fabs(x-tmp.x) < ESP) && (fabs(y-tmp.y) < ESP);
    }
    int operator * (const Point &tmp) const{
       double t = x*tmp.y - y*tmp.x;

       if(t > ESP)return 1;
       if(fabs(t) < ESP)return 0;
       return -1;
    }
};
struct Segment
{
    Point A, B;
    Segment(Point t1=0, Point t2=0){A=t1, B=t2;}
};
bool Find(Segment t, Segment seg[], int N)
{
    for(int i=1; i<=N; i++)
    {///使用叉积判断是否想交
        int k = fabs((t.A-t.B)*(seg[i].A-t.B) + (t.A-t.B)*(seg[i].B-t.B));

        if(k==2)return false;
    }

    return true;
}

int main()
{
    int N, T;

    scanf("%d", &T);

    while(T--)
    {
        double x1, x2, y1, y2;
        Point p[MAXN];
        Segment seg[MAXN];

        scanf("%d", &N);

        int M=0;

        for(int i=1; i<=N; i++)
        {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            p[M++]=Point(x1, y1), p[M++]=Point(x2, y2);
            seg[i]=Segment(p[M-2], p[M-1]);
        }

        int ok = false;

        for(int i=0; i<M && !ok; i++)
        for(int j=i+1; j<M && !ok; j++)
        {
            if(p[i] == p[j])
                continue;

            ok = Find(Segment(p[i], p[j]), seg, N);
        }

        if(ok)printf("Yes!
");
        else printf("No!
");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/liuxin13/p/4789194.html