【bzoj2618】[Cqoi2006]凸多边形 半平面交
题目描述

则相交部分的面积为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]凸多边形 半平面交的更多相关文章
- BZOJ2618[Cqoi2006]凸多边形——半平面交
题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第 ...
- bzoj2618[Cqoi2006]凸多边形 半平面交
这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方 ...
- P4196 [CQOI2006]凸多边形 半平面交
\(\color{#0066ff}{题目描述}\) 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. \(\color{#0066f ...
- luogu4196 [CQOI2006]凸多边形 半平面交
据说pkusc出了好几年半平面交了,我也来水一发 ref #include <algorithm> #include <iostream> #include <cstdi ...
- POJ3525 半平面交
题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...
- bzoj 4445 小凸想跑步 - 半平面交
题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...
- 【kuangbin专题】计算几何_半平面交
1.poj3335 Rotating Scoreboard 传送:http://poj.org/problem?id=3335 题意:就是有个球场,球场的形状是个凸多边形,然后观众是坐在多边形的边上的 ...
- bzoj 3190 赛车 半平面交
直接写的裸的半平面交,已经有点背不过模板了... 这题卡精度,要用long double ,esp设1e-20... #include<iostream> #include<cstd ...
- BZOJ 4445 [Scoi2015]小凸想跑步:半平面交
传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...
随机推荐
- udp重发java实现
最近在处理框架通讯方面的问题,通过积累的开发经验,其实在很多情况(尤其是实时大数据量),udp是占有很多优势的:不需要连接,只管发送,理论上要快很多; 另外在穿墙上占有很大优势: 但是最大的一个问题就 ...
- this以及执行上下文概念的重新认识
在理解this的绑定过程之前,必须要先明白调用位置,调用位置指的是函数在代码中被调用的位置,而不是声明所在的位置. (ES6的箭头函数不在该范围内,它的this在声明时已经绑定了,而不是取决于调用时. ...
- 总结JavaScript常用数组操作方法,包含ES6方法
一.concat() concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,仅会返回被连接数组的一个副本. var arr1 = [1,2,3]; var arr2 = [4,5]; ...
- PXE自动化安装CentOS6/7
服务器为centos7 安装前准备:关闭防火墙和SELINUX 虚拟机准备第二块网卡,设置主机模式,关闭虚拟机网络配置中主机模式的DHCP功能,并设置静态IP nmcli c a con-name e ...
- python__基础 : 类的 __slots__ 方法
实例在创建出来之后,可以动态的添加属性和方法, 那如果想要限制添加的实例属性,可以用一下 __slots__ 这个东西: class Test(object): __slots__ = ('name' ...
- 数据结构学习-BST二叉查找树 : 插入、删除、中序遍历、前序遍历、后序遍历、广度遍历、绘图
二叉查找树(Binary Search Tree) 是一种树形的存储数据的结构 如图所示,它具有的特点是: 1.具有一个根节点 2.每个节点可能有0.1.2个分支 3.对于某个节点,他的左分支小于自身 ...
- Git Pro Book
目录 2nd Edition (2014) Switch to 1st Edition Download Ebook The entire Pro Git book, written by Scott ...
- 9 Django 模型层(2) --多表操作
创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系( ...
- [bzoj2932][POI1999]树的染色问题
被百度搜到的题解(论文?)坑了. 写的那玩意好像石乐志... Description 一棵二叉树采用以下规则描述: 1.如果一个节点度数为0,则仅用一个元素“0”来描述它. 2.如果一个节点度数为1, ...
- Android 打印方法调用堆栈
RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Log.w(" ...