POJ 3304 Segments

如果存在一条穿过所有线段的直线,那么这条直线的垂线就满足题意了。

如果存在一条穿过所有线段的直线,那么存在一条穿过所有线段,且穿过了不同线段的两个端点的这样一条直线。

算几真TM烦各种细节各种挂精度。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 205
#define eps 1e-8
using namespace std;
struct point
{
    double x,y;
    point (double x,double y):x(x),y(y) {}
    point () {}
    friend point operator -(point x,point y)
    {
        return point(x.x-y.x,x.y-y.y);
    }
}p[maxn];
struct line
{
    point x,dt;
    line (point x,point dt):x(x),dt(dt) {}
    friend double operator *(line x,line y)
    {
        return x.dt.x*y.dt.y-x.dt.y*y.dt.x;
    }
    line () {}
}l[maxn];
int t,n;
double x1x,y1y,x2x,y2y;
double get_y(double x,line y)
{
    double k=(x-y.x.x)/(y.dt.x);
    return y.x.y+k*y.dt.y;
}
bool check(line x,line y)
{
    if (!x.dt.x)
    {
        if (!y.dt.x) return (fabs(x.x.x-y.x.x)<eps);
        else
        {
            double mn=min(y.x.x,y.x.x+y.dt.x),mx=max(y.x.x,y.x.x+y.dt.x);
            return ((x.x.x>=mn) && (x.x.x<=mx));
        }
    }
    else
    {
        double y1=get_y(y.x.x,x),y2=get_y(y.x.x+y.dt.x,x);
        return (y1-y.x.y)*(y2-(y.x.y+y.dt.y))<=eps;
    }
}
bool work()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%lf%lf%lf%lf",&x1x,&y1y,&x2x,&y2y);
        p[2*i-1]=point(x1x,y1y);p[2*i]=point(x2x,y2y);
        l[i]=line(p[2*i-1],p[2*i]-p[2*i-1]);
    }
    for (int i=1;i<=2*n;i++)
        for (int j=i+1;j<=2*n;j++)
        {
            line now=line(p[i],p[j]-p[i]);int flag=1;
            for (int k=1;k<=n;k++)
                if (!check(now,l[k])) {flag=0;break;}
            if (flag) return true;
        }
    return false;
}
int main()
{
    scanf("%d",&t);
    for (int i=1;i<=t;i++)
    {
        if (work()) printf("Yes!
");
        else printf("No!
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ziliuziliu/p/6271199.html