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

    半平面交

    POJ 2451

    敲了个板子,比带花树稍微好一些,但是还是很麻烦...

    写了点注释

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define Point Vector
    const int N=2e4+10;
    struct Vector
    {
        double x,y;
        Vector(){}
        Vector(double x,double y){this->x=x,this->y=y;}
        double angle(){return atan2(y,x);}//极角
        Vector friend operator *(Vector a,double b){return Vector(a.x*b,a.y*b);}//向量数乘
        Vector friend operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}//向量加
        Vector friend operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}//向量减
    }qp[N],ans[N];
    const double eps=1e-7;
    bool dcmp(double a,double b){return fabs(a-b)<eps;}//是否相等
    struct Line
    {
        Point s,t;double ang;
        Line(){}
        Line(Point s,Point t){this->s=s,this->t=t,this->ang=(t-s).angle();}
    }Li[N],ql[N];
    double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}//向量外积
    bool cmp(Line a,Line b){return dcmp(a.ang,b.ang)?cross(a.t-a.s,b.t-a.s)+eps<0:a.ang<b.ang;}//极角从小到大排序
    bool pingxing(Line a,Line b){return dcmp(cross(a.t-a.s,b.t-b.s),0);}//平行外积为0
    Point jiaodian(Line a,Line b){return a.s+(a.t-a.s)*(cross(a.s-b.s,b.t-b.s)/cross(b.t-b.s,a.t-a.s));}//交点,这个要画图
    double area(Point *s,int n)//求凸多边形面积
    {
        double ret=0;
        s[n+1]=s[1];
        for(int i=1;i<=n;i++) ret+=cross(s[i],s[i+1]);
        return fabs(ret/2);
    }
    bool isrig(Line a,Point b){return cross(a.t-a.s,b-a.s)+eps<0;}//判断点是否在向量右边
    int l,r;
    bool SI(Line *li,int n,Point *ret,int &m)//增量法求半平面交
    {
        std::sort(li+1,li+1+n,cmp);
        ql[l=r=1]=li[1];
        for(int i=2;i<=n;i++)
            if(!dcmp(li[i].ang,li[i-1].ang))//如果这个直线和上一条极角相等,取前面一条靠左边的
            {
                while(l<r&&isrig(li[i],qp[r-1])) --r;//把队尾超过的点扔了
                while(l<r&&isrig(li[i],qp[l])) ++l;//把队头超过的点扔了
                if(l<=r) qp[r]=jiaodian(ql[r],li[i]);//加入一个交点
                ql[++r]=li[i];//加入直线
                if(l<r&&(pingxing(ql[l],ql[l+1])||pingxing(ql[r],ql[r-1]))) return false;//向量反向,半平面交是直线
            }
        while(l<r&&isrig(ql[l],qp[r-1])) --r;//扔掉队尾不合法的
        while(l<r&&isrig(ql[r],qp[l])) ++l;//扔掉队首不合法的
        if(r-l<=1) return false;//直线少于2个,没得
        qp[r]=jiaodian(ql[l],ql[r]);//首尾交点
        m=0;for(int i=l;i<=r;i++) ret[++m]=qp[i];
        return true;
    }
    int main()
    {
        int n,m;
        scanf("%d",&n);Point a,b,c,d;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
            Li[i]=Line(a,b);
        }
        a=Point(0,0),b=Point(10000,0),c=Point(10000,10000),d=Point(0,10000);
        Li[++n]=Line(a,b),Li[++n]=Line(b,c),Li[++n]=Line(c,d),Li[++n]=Line(d,a);
        if(SI(Li,n,ans,m)) printf("%.1lf
    ",area(ans,m));
        else puts("0.0");
        return 0;
    }
    
  • 相关阅读:
    WPF 中依赖属性的继承(Inherits)
    使用FluentValidation来进行数据有效性验证
    使用ASP.Net WebAPI构建REST服务(六)——Self-Host
    使用ASP.Net WebAPI构建REST服务(五)——客户端
    使用ASP.Net WebAPI构建REST服务(四)——参数绑定
    使用ASP.Net WebAPI构建REST服务(三)——返回值
    使用ASP.Net WebAPI构建REST服务(二)——路由
    使用ASP.Net WebAPI构建REST服务(一)——简单的示例
    WPF在代码中创建DataTemplate时候的异常
    一个简单的WeakList的实现
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10192415.html
Copyright © 2011-2022 走看看