• bzoj 2618 2618: [Cqoi2006]凸多边形(半平面交)


    2618: [Cqoi2006]凸多边形

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 656  Solved: 340
    [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<=103<=mi<=50,每维坐标为[-1000,1000]内的整数




    Source

    【思路】

      半平面交即若干个直线代表的半平面的重合部分。

    【代码】

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 const int eps = 1e-10;
     9 
    10 struct Pt {
    11     double x,y;
    12     Pt (double x=0,double y=0) :x(x),y(y) {}
    13 };
    14 typedef Pt vec;
    15 
    16 vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
    17 vec operator + (vec a,vec b) { return vec(a.x+b.x,a.y+b.y); }
    18 vec operator * (vec a,double x) { return vec(a.x*x,a.y*x); }
    19 
    20 double cross(Pt a,Pt b) { return a.x*b.y-a.y*b.x; }
    21 
    22 struct Line {
    23     Pt p; vec v; double ang;
    24     Line() {}
    25     Line(Pt p,vec v) :p(p),v(v) { ang=atan2(v.y,v.x); }
    26     bool operator < (const Line& rhs) const {
    27         return ang < rhs.ang;
    28     }
    29 };
    30 bool onleft(Line L,Pt p) { return cross(L.v,p-L.p)>0; }
    31 Pt getLineInter(Line a,Line b) {
    32     vec u=a.p-b.p;
    33     double t=cross(b.v,u)/cross(a.v,b.v);
    34     return a.p+a.v*t;
    35 }
    36 vector<Pt> HPI(vector<Line> L) {
    37     int n=L.size();
    38     sort(L.begin(),L.end());
    39     int f,r;
    40     vector<Pt> p(n) , ans;
    41     vector<Line> q(n);
    42     q[f=r=0]=L[0];
    43     for(int i=1;i<n;i++) {
    44         while(f<r && !onleft(L[i],p[r-1])) r--;
    45         while(f<r && !onleft(L[i],p[f])) f++;
    46         q[++r]=L[i];
    47         if(fabs(cross(q[r].v,q[r-1].v))<eps) {
    48             r--;
    49             if(onleft(q[r],L[i].p)) q[r]=L[i];
    50         }
    51         if(f<r) p[r-1]=getLineInter(q[r-1],q[r]);
    52     }
    53     while(f<r && !onleft(q[f],p[r-1])) r--;
    54     if(r-f<=1) return ans;
    55     p[r]=getLineInter(q[r],q[f]);
    56     for(int i=f;i<=r;i++) ans.push_back(p[i]);
    57     return ans;
    58 }
    59 vector<Line> L;
    60 vector<Pt> p;
    61 Pt t[55];
    62 int n,m;
    63 
    64 int main() {
    65     scanf("%d",&n);
    66     for(int i=0;i<n;i++) {
    67         scanf("%d",&m);
    68         for(int i=0;i<m;i++)
    69             scanf("%lf%lf",&t[i].x,&t[i].y);
    70         for(int i=1;i<m;i++)
    71             L.push_back(Line(t[i-1],t[i]-t[i-1]));
    72         L.push_back(Line(t[m-1],t[0]-t[m-1]));
    73     }
    74     p = HPI(L);
    75     double ans=0.0; int m=p.size();
    76     for(int i=1;i<m-1;i++)
    77         ans += cross(p[i]-p[0],p[i+1]-p[0]);
    78     printf("%.3lf",ans/2);
    79     return 0;
    80 }
    View Code
  • 相关阅读:
    viewer.js 显示图片名称和照片属性
    js中判断数组中是否包含某元素的方法(转载)
    js脚本如何更新, js后加?v=版本号的原因(转载)
    iview Carousel 走马灯或轮播图 点击事件失效
    sqlserver 查询表中所有字段的最大长度(转载)
    Ueditor文字和echarts图片 生成 word 前端解决方案
    Spark Streaming Backpressure分析
    Spark任务调度流程及调度策略分析
    Spark资源调度及任务调度
    spark streaming流式计算---监听器
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5184003.html
Copyright © 2020-2023  润新知