zoukankan      html  css  js  c++  java
  • 【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 }
  • 相关阅读:
    mysql的存储过程与事务入门
    关于CreateProcess函数一些经验
    windows下dump文件调试
    指针相关
    nsi脚本中执行.bat文件要隐藏dos窗口问题
    C 预处理
    __declspec(dllimport)与__declspec(dllexport)作用总结
    [转]window下使用SetUnhandledExceptionFilter捕获让程序的崩溃
    字符集与编码[转]
    vc下项目的头文件包含目录以及库导入预计库目录设置
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11123194.html
Copyright © 2011-2022 走看看