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


    2618: [Cqoi2006]凸多边形

    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]内的整数

    solution:

    转化为很多直线的半平面交

    code:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      7 using namespace std;
      8 #define Maxn 1100
      9 
     10 struct P
     11 {
     12     double x,y;
     13     P()
     14     {
     15         x=y=0;
     16     }
     17     P(double x,double y):x(x),y(y) {}
     18     friend P operator - (P x,P y)
     19     {
     20         return P(x.x-y.x,x.y-y.y);
     21     }
     22     friend P operator + (P x,P y)
     23     {
     24         return P(x.x+y.x,x.y+y.y);
     25     }
     26     friend P operator * (P x,double y)
     27     {
     28         return P(x.x*y,x.y*y);
     29     }
     30     friend double operator * (P x,P y)
     31     {
     32         return x.x*y.y-x.y*y.x;
     33     }
     34     friend double operator / (P x,P y)
     35     {
     36         return x.x*y.x+x.y*y.y;
     37     }
     38 } a[Maxn];
     39 struct L
     40 {
     41     P a,b,v;
     42     
     43     // v为方向向量
     44     
     45     double slop;
     46 
     47     friend bool operator < (L a,L b)
     48     {
     49         return (a.slop!=b.slop)?(a.slop<b.slop):a.v*(b.b-a.a)>0;
     50         // 极角相同,保留相对在左侧的
     51     }
     52     friend P inter(L b,L a)
     53     {
     54         P nw=b.a-a.a;
     55         double tt=(nw*a.v)/(a.v*b.v);
     56         return b.a+b.v*tt;
     57         // 求两个直线的交点 
     58     }
     59 
     60     friend bool jud(P x,L c)
     61     {
     62         return c.v*(x-c.a)<0;
     63     }
     64 
     65 } l[Maxn],q[Maxn];
     66 int cnt,tot;
     67 
     68 void ffind()
     69 {
     70     for(int i=1; i<=cnt; i++) l[i].v=l[i].b-l[i].a,l[i].slop=atan2(l[i].v.y,l[i].v.x);
     71     sort(l+1,l+1+cnt);
     72     int L=1,R=0;
     73     tot=0;
     74     for(int i=1; i<=cnt; i++)
     75     {
     76         if(l[i].slop!=l[i-1].slop) tot++;
     77         l[tot]=l[i];
     78     }
     79     cnt=tot;
     80     tot=0;
     81     q[++R]=l[1];
     82     q[++R]=l[2];
     83     for(int i=3; i<=cnt; i++)
     84     {
     85         while(L<R&&jud(inter(q[R-1],q[R]),l[i])) R--;
     86         while(L<R&&jud(inter(q[L+1],q[L]),l[i])) L++;
     87         q[++R]=l[i];
     88     }
     89     while(L<R&&jud(inter(q[R-1],q[R]),q[L])) R--;
     90     while(L<R&&jud(inter(q[L+1],q[L]),q[R])) L++;
     91     q[R+1]=q[L];
     92     for(int i=L; i<=R; i++) a[++tot]=inter(q[i],q[i+1]);
     93 }
     94 
     95 void init()
     96 {
     97     int n;
     98     scanf("%d",&n);
     99     cnt=0;
    100     for(int i=1; i<=n; i++)
    101     {
    102         int m;
    103         scanf("%d",&m);
    104         P ft,now,nw;
    105         scanf("%lf%lf",&ft.x,&ft.y);
    106         now=ft;
    107         for(int j=2; j<=m; j++)
    108         {
    109             scanf("%lf%lf",&nw.x,&nw.y);
    110             l[++cnt].b=nw,l[cnt].a=now;
    111             now=nw;
    112         }
    113         l[++cnt].a=now;
    114         l[cnt].b=ft;
    115     }
    116     // 必须保证是逆时针输入点
    117 }
    118 
    119 void get_area()// 任意多边形的面积
    120 {
    121     double ans=0;
    122     for(int i=1; i<tot; i++) ans+=a[i]*a[i+1];
    123     ans+=a[tot]*a[1];
    124     if(tot<3) ans=0;
    125     printf("%.3lf
    ",ans/2);
    126 }
    127 
    128 int main()
    129 {
    130     init();
    131     ffind();
    132     get_area();
    133     return 0;
    134 
    135 }
  • 相关阅读:
    使用FolderBrowserDialog组件选择文件夹
    使用OpenFileDialog组件打开多个文
    使用OpenFileDialog组件打开对话框
    获取弹出对话框的相关返回值
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1139 First Contact (30 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1138 Postorder Traversal (25 分)
    PAT 甲级 1137 Final Grading (25 分)
    PAT 甲级 1137 Final Grading (25 分)
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11123194.html
Copyright © 2020-2023  润新知