zoukankan      html  css  js  c++  java
  • LA2218半平面交

    没有想到这个题可以转化成解方程组的形式,就像线性规划一样,觉得好神奇。《训练指南》上的解析挺详细的,就不写了。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=110;
    const double eps=1e-8;
    struct Point
    {
        double x,y;
        Point(double x=0,double y=0):x(x),y(y) {}
    };
    typedef Point Vector;
    struct DLine//有向直线directed line
    {
        Point P;
        Vector v;
        double ang;
        DLine() {}
        DLine(Point P,Vector v):P(P),v(v)
        {
            ang=atan2(v.y,v.x);
        }
        bool operator < (const DLine& L) const
        {
            return ang<L.ang;
        }
    };
    
    Vector operator + (Vector A,Vector B)
    {
        return Vector(A.x+B.x,A.y+B.y);
    }
    Vector operator - (Vector A,Vector B)
    {
        return Vector(A.x-B.x,A.y-B.y);
    }
    Vector operator * (Vector A,double p)
    {
        return Vector(A.x*p,A.y*p);
    }
    int dcmp(double x)
    {
        if(fabs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    bool operator == (const Point& a,const Point& b)//两点相等
    {
        return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
    }
    double Dot(Vector A,Vector B)
    {
        return A.x*B.x+A.y*B.y;
    }
    double Length(Vector A)
    {
        return sqrt(Dot(A,A));
    }
    double Cross(Vector A,Vector B)
    {
        return A.x*B.y-A.y*B.x;
    }
    Vector Normal(Vector A)//向量的单位法线,即左转90度
    {
        double L=Length(A);
        return Vector(-A.y/L,A.x/L);
    }
    
    bool OnLeft(DLine L,Point p)//判断点p是否在有向直线L的左边
    {
        return Cross(L.v,p-L.P)>0;
    }
    Point GetIntersection(DLine a,DLine b)//有向直线交点,假设交点唯一
    {
        Vector u=a.P-b.P;
        double t=Cross(b.v,u)/Cross(a.v,b.v);
        return a.P+a.v*t;
    }
    int HalfPlaneIntersection(DLine* L,int n,Point* poly)//半平面交
    {
        sort(L,L+n);
        int first,last;
        Point *p=new Point[n];
        DLine *q=new DLine[n];
        q[first=last=0]=L[0];
        for(int i=1;i<n;i++)
        {
            while(first<last && !OnLeft(L[i],p[last-1])) last--;
            while(first<last && !OnLeft(L[i],p[first])) first++;
            q[++last]=L[i];
            if(fabs(Cross(q[last].v,q[last-1].v))<eps)
            {
                last--;
                if(OnLeft(q[last],L[i].P)) q[last]=L[i];
            }
            if(first<last) p[last-1]=GetIntersection(q[last-1],q[last]);
        }
        while(first<last && !OnLeft(q[first],p[last-1])) last--;
        if(last-first <= 1) return 0;
        p[last]=GetIntersection(q[last],q[first]);
        int m=0;
        for(int i=first;i<=last;i++) poly[m++]=p[i];
        return m;
    }
    Point poly[maxn];
    DLine L[maxn];
    int V[maxn],U[maxn],W[maxn];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            for(int i=0;i<n;i++)
                scanf("%d%d%d",&V[i],&U[i],&W[i]);
            for(int i=0;i<n;i++)
            {
                int cnt=0,ok=1;
                double k=10000;
                for(int j=0;j<n;j++)
                    if(i!=j)
                    {
                        if(V[i]<=V[j] && U[i]<=U[j] && W[i]<=W[j]) {ok=0;break;}
                        if(V[i]>=V[j] && U[i]>=U[j] && W[i]>=W[j]) continue;
                        double a=(k/V[j]-k/W[j])-(k/V[i]-k/W[i]);
                        double b=(k/U[j]-k/W[j])-(k/U[i]-k/W[i]);
                        double c=k/W[j]-k/W[i];
                        Point p=Point(-c/a,0);
                        Vector v(b,-a);
                        L[cnt++]=DLine(p,v);
                    }
                if(ok)
                {
                    L[cnt++]=DLine(Point(0,0),Vector(0,-1));
                    L[cnt++]=DLine(Point(0,0),Vector(1,0));
                    L[cnt++]=DLine(Point(0,1),Vector(-1,1));
                    if(!HalfPlaneIntersection(L,cnt,poly)) ok=0;
                }
                if(ok) printf("Yes
    ");
                else printf("No
    ");
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    JS Dom_API
    JS 动态表格(添加、删除行)
    将本地网页上传到 apache2 及 github 的步骤
    软件工程之美 第一周
    树莓派安装芯片驱动并测试
    Visoul Studio 2019 远程调试 中文乱码
    Visoul Studio 2019 远程调试 RaspberryPi C 项目
    课设提纲
    PHP PDO 一 : 常用方法
    设置子域名及申请其证书
  • 原文地址:https://www.cnblogs.com/54zyq/p/3236662.html
Copyright © 2011-2022 走看看