题目描述

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

则相交部分的面积为5.233。

输入

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

输出

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

样例输入

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

样例输出

5.233


题解

半平面交

题意即求一堆半平面的公共部分,即半平面交。

暴力半平面交可以过,但还是学了一下双端队列求半平面交的方法:

不妨设直线的右侧为半平面,那么把所有半平面按照直线的极角从小到大排序,极角相同的保留限制条件最严格的,即最右侧的。

排序去重以后扫一遍所有直线,判断分别队尾交点和队头交点是否在当前直线左端,在的话就踢出双端队列。然后再把当前半平面压入双端队列队尾。

最后,队尾的交点与队首可能不满足条件,因此还要弹掉队尾不合法的部分。

求面积的话直接上叉积就可以了。

废话不多说,直接上代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define eps 1e-9
#define N 510
using namespace std;
struct point
{
double x , y;
point() {}
point(double a , double b) {x = a , y = b;}
point operator+(const point &a)const {return point(x + a.x , y + a.y);}
point operator-(const point &a)const {return point(x - a.x , y - a.y);}
point operator*(const double &a)const {return point(a * x , a * y);}
}p[N];
struct line
{
point p , v;
double ang;
}a[N] , q[N] , c[N];
inline double cross(point a , point b) {return a.x * b.y - a.y * b.x;}
inline bool left(line a , point b) {return cross(a.v , b - a.p) > eps;}
inline point inter(line a , line b)
{
point u = a.p - b.p;
double tmp = cross(b.v , u) / cross(a.v , b.v);
return a.p + a.v * tmp;
}
bool cmp(const line &a , const line &b)
{
return fabs(a.ang - b.ang) < eps ? left(a , b.p) : a.ang < b.ang;
}
int main()
{
int n , i , j , m , cnt = 0 , tot = 1 , l = 1 , r = 1;
double ans = 0;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d" , &m);
for(j = 1 ; j <= m ; j ++ ) scanf("%lf%lf" , &p[j].x , &p[j].y);
for(j = 1 ; j <= m ; j ++ ) a[++cnt].p = p[j] , a[cnt].v = p[j] - p[j % m + 1] , a[cnt].ang = atan2(a[cnt].v.y , a[cnt].v.x);
}
sort(a + 1 , a + cnt + 1 , cmp);
for(i = 2 ; i <= cnt ; i ++ )
if(fabs(a[i].ang - a[i - 1].ang) > eps)
a[++tot] = a[i];
q[1] = a[1];
for(i = 2 ; i <= tot ; i ++ )
{
while(l < r && left(a[i] , p[r - 1])) r -- ;
while(l < r && left(a[i] , p[l])) l ++ ;
q[++r] = a[i];
if(l < r) p[r - 1] = inter(q[r - 1] , q[r]);
}
while(l < r && left(q[l] , p[r - 1])) r -- ;
p[r] = inter(q[l] , q[r]) , p[r + 1] = p[l];
for(i = l ; i <= r ; i ++ ) ans += cross(p[i] , p[i + 1]);
printf("%.3lf\n" , ans / 2);
return 0;
}

【bzoj2618】[Cqoi2006]凸多边形 半平面交的更多相关文章

  1. BZOJ2618[Cqoi2006]凸多边形——半平面交

    题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第 ...

  2. bzoj2618[Cqoi2006]凸多边形 半平面交

    这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方 ...

  3. P4196 [CQOI2006]凸多边形 半平面交

    \(\color{#0066ff}{题目描述}\) 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. \(\color{#0066f ...

  4. luogu4196 [CQOI2006]凸多边形 半平面交

    据说pkusc出了好几年半平面交了,我也来水一发 ref #include <algorithm> #include <iostream> #include <cstdi ...

  5. POJ3525 半平面交

    题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...

  6. bzoj 4445 小凸想跑步 - 半平面交

    题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...

  7. 【kuangbin专题】计算几何_半平面交

    1.poj3335 Rotating Scoreboard 传送:http://poj.org/problem?id=3335 题意:就是有个球场,球场的形状是个凸多边形,然后观众是坐在多边形的边上的 ...

  8. bzoj 3190 赛车 半平面交

    直接写的裸的半平面交,已经有点背不过模板了... 这题卡精度,要用long double ,esp设1e-20... #include<iostream> #include<cstd ...

  9. BZOJ 4445 [Scoi2015]小凸想跑步:半平面交

    传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...

随机推荐

  1. JS中的var、let、const

    1.var 在全局window中申明则为全局变量,是全局对象 window 的属性. var sum = 0 console.log(window.sum) console.log(sum); 在函数 ...

  2. python中的zipfile

    zipfile - Work with ZIP archives ZipFile.namelist() Return a list of archive members by name. 返回压缩成员 ...

  3. (转)基于REST架构的Web Service设计

    原文出处:http://www.williamlong.info/archives/1728.html ------------------------------------------------ ...

  4. js开发中常用小技巧

    1.获取指定范围内的随机数 function getRadomNum(min,max){ return Math.floor(Math.random() * (max - min + 1)) + mi ...

  5. laravel通过make auth实现手机号登录

    首先按照Laravel的教程,安装认证系统. php artisan make:auth php artisan migrate laravel已经安装完成认证系统,默认注册和登录都是用邮箱. 如果想 ...

  6. 重头开始学Qt——day1

    以前学过Qt,但只是为了学分,现在重学. 1. 认识Qt应用程序框架 直接新建一个项目后,自动生成了一下文件,下面一个个理解. (1)main.cpp main.cpp中特别的是QApplicatio ...

  7. Robots Gym - 101915G

    传送门 The Robotics Olympiad teams were competing in a contest. There was a tree drawn on the floor, co ...

  8. 9.1 mysql+centos7+主从复制

    MYSQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的 ...

  9. 3 网格 landing page

    0.大框架 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...

  10. \r \r\n \t的区别

    \n 软回车:      在Windows 中表示换行且回到下一行的最开始位置.相当于Mac OS 里的 \r 的效果.      在Linux.unix 中只表示换行,但不会回到下一行的开始位置. ...