zoukankan      html  css  js  c++  java
  • 【BZOJ-2618】凸多边形 计算几何 + 半平面交 + 增量法 + 三角剖分

    2618: [Cqoi2006]凸多边形

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 959  Solved: 489
    [Submit][Status][Discuss]

    Description

    逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
     

     

    则相交部分的面积为5.233。

    Input

    第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

    Output

        输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

    Sample Input

    2
    6
    -2 0
    -1 -2
    1 -2
    2 0
    1 2
    -1 2
    4
    0 -3
    1 -1
    2 2
    -1 0

    Sample Output

    5.233

    HINT

    100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

    Source

    Solution

    裸半平面交

    这里用的O(n^{2})的增量法,求完半平面交后再求多边形面积就好了,三角剖分一下就可以

    一个不错的讲解

    具体的做法:

    •初始化时加上一个范围巨大的“框”
    •每次拿一个新的半平面切割原先的凸集
    •保留在新加直线左边的点,删除右边的,有向直线与多边形相交产生的新的点加入到新多边形内

    Code

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    using namespace std;
    struct Vector
    {
        double x,y;
        Vector(double X=0,double Y=0) {x=X,y=Y;}
    };
    typedef Vector Point;
    typedef vector<Point> Polygon;
    Polygon polygon;
    #define MAXN 20
    #define MAXM 100
    Point P[MAXN][MAXM];
    #define eps 1e-8
    #define INF 1000
    const double pi= acos(-1.0);
    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});}
    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 Vector& a,const Vector& 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 Len(Vector A) {return sqrt(Dot(A,A));}
    double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
    Point GLI(Point P,Vector v,Point Q,Vector w) {Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t;}
    double DisTL(Point P,Point A,Point B) {Vector v1=B-A,v2=P-A; return fabs(Cross(v1,v2)/Len(v1));}
    bool OnSegment(Point P,Point A,Point B) {return dcmp(DisTL(P,A,B))==0&&dcmp(Dot(P-A,P-B))<0&&!(P==A)&&!(P==B);}
    double PolygonArea(Polygon p)
    {
        double area=0;
        int n=p.size();
        for(int i=1;i<n-1;i++)
            area+=Cross(p[i]-p[0],p[i+1]-p[0]);
        return area/2;
    }
    Polygon CutPolygon(Polygon poly,Point A,Point B)
    {
        Polygon newpoly;
        Point C,D,ip;
        int n=poly.size(),i;
        for(i=0;i<n;i++)
        {
            C=poly[i];
            D=poly[(i+1)%n];
            if(dcmp(Cross(B-A,C-A))>=0)
                newpoly.push_back(C);
            if(dcmp(Cross(B-A,D-C))!=0)
            {
                ip=GLI(A,B-A,C,D-C);
                if(OnSegment(ip,C,D))
                    newpoly.push_back(ip);
            }
        }
        return newpoly;
    }
    void InitPolygon(Polygon &poly,double inf)
    {
        poly.clear();
        poly.push_back((Point){-inf,-inf});
        poly.push_back((Point){inf,-inf});
        poly.push_back((Point){inf,inf});
        poly.push_back((Point){-inf,inf});
    }    
    void Debug()
    {
        for (int j=0; j<polygon.size(); j++)
            printf("(%.1lf,%.1lf)-->",polygon[j].x,polygon[j].y);
        printf("(%.1lf,%.1lf)",polygon[0].x,polygon[0].y);
        puts("");
    }
    int main()
    {
        int N,M;
          scanf("%d",&N);
        InitPolygon(polygon,INF);
        for (int i=1; i<=N; i++)
            {            
                scanf("%d",&M);
                for (int j=1; j<=M; j++)
                    scanf("%lf%lf",&P[i][j].x,&P[i][j].y);
                P[i][M+1]=P[i][1];
                for (int j=1; j<=M; j++)
                    {polygon=CutPolygon(polygon,P[i][j],P[i][j+1]); /*Debug();*/}
            }
        printf("%.3lf
    ",PolygonArea(polygon));
        return 0;
    }

    自己调个模板,p事怎么这么多QAQ

  • 相关阅读:
    Disruptor-架构思维的转变
    高性能队列——Disruptor
    flink Standalone Cluster
    Kafka 0.11.0.0 实现 producer的Exactly-once 语义(官方DEMO)
    Kafka 0.11.0.0 实现 producer的Exactly-once 语义(中文)
    Kafka 0.11.0.0 实现 producer的Exactly-once 语义(英文)
    flink window的early计算
    Flink 的Window 操作(基于flink 1.3描述)
    Flink Pre-defined Timestamp Extractors / Watermark Emitters(预定义的时间戳提取/水位线发射器)
    Flink Event Time Processing and Watermarks(文末有翻译)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5682592.html
Copyright © 2011-2022 走看看