\(\color{#0066ff}{题目描述}\)

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

则相交部分的面积为5.233。

\(\color{#0066ff}{输入格式}\)

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

\(\color{#0066ff}{输出格式}\)

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

\(\color{#0066ff}{输入样例}\)

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

\(\color{#0066ff}{输出样例}\)

5.233

\(\color{#0066ff}{数据范围与提示}\)

100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

\(\color{#0066ff}{题解}\)

半平面交裸题

开两个结构体储存点和线

根据输入方式,自己定义直线方向,那么半平面的方向就确定了

代码中规定的方向是向量左边

两个向量求交(\(AC, BE\))

做出这样的平行四边形

过E作EH,过p(交点)作PG

显然BPG,BEH相似,而且作的两条线为平行四边形的高

又因为两个平行四边形的底相等

所以高之比等于相似比?

通过叉积可以获得面积比(相似比)

然后\(p = B + k * v_2\)

以上为向量求交点

我们维护一个双端队列

每次来一跳新的直线,把收到影响的队首,队尾弹出

最后队列里就是有效直线

把相邻的交点都求出来,那么这个多边形的面积就是半平面交的面积

#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {
char ch; int x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 505;
double eps = 1e-8;
int T(double x) {
if(x > eps) return 1;
if(x < -eps) return -1;
return 0;
}
struct node {
double x, y;
node(double x = 0, double y = 0): x(x), y(y) {}
node operator + (const node &b) const {
return node(x + b.x, y + b.y);
}
node operator - (const node &b) const {
return node(x - b.x, y - b.y);
}
double operator ^ (const node &b) const {
return x * b.y - y * b.x;
}
double jj() const {
return atan2(y, x);
}
node operator * (double b) const {
return node(x * b, y * b);
}
}e[maxn]; struct line {
node from, to;
line(node from = node(), node to = node()): from(from), to(to) {}
double jj() const {
return (to - from).jj();
}
bool operator < (const line &b) const {
return T(jj() - b.jj()) == 0? T((to - from) ^ (b.to - from)) > 0 : T(jj() - b.jj()) < 0;
}
}a[maxn], q[maxn];
int n, head, tail, ji;
node to(line i, line j) {
node x = i.to - i.from, y = j.to - j.from, z = j.from - i.from;
return j.from + y * ((z ^ x) / (x ^ y));
}
bool jud(line x, line y, line z) {
node p = to(x, y);
return ((z.to - z.from) ^ (p - z.from)) < 0;
}
void work() {
std::sort(a + 1, a + ji + 1);
int cnt = 0;
for(int i = 1; i <= ji; i++) {
if(T(a[i].jj() - a[i - 1].jj())) cnt++;
a[cnt] = a[i];
}
head = 1, tail = 0;
q[++tail] = a[1], q[++tail] = a[2];
for(int i = 3; i <= cnt; i++) {
while(head < tail && jud(q[tail - 1], q[tail], a[i])) tail--;
while(head < tail && jud(q[head + 1], q[head], a[i])) head++;
q[++tail] = a[i];
}
while(head < tail && jud(q[tail - 1], q[tail], q[head])) tail--;
while(head < tail && jud(q[head + 1], q[head], q[tail])) head++;
q[tail + 1] = q[head];
ji = 0;
for(int i = head; i <= tail; i++) e[++ji] = to(q[i], q[i + 1]);
} int main() {
n = in();
for(int i = 1; i <= n; i++) {
int F = in();
for(int j = 1; j <= F; j++)
e[j].x = in(), e[j].y = in();
e[F + 1] = e[1];
for(int j = 1; j <= F; j++) a[++ji] = line(e[j], e[j + 1]);
}
work();
double ans = 0;
e[ji + 1] = e[1];
if(ji > 2) for(int i = 1; i <= ji; i++) ans += (e[i] ^ e[i + 1]);
printf("%.3f", fabs(ans) / 2.0);
return 0;
}

P4196 [CQOI2006]凸多边形 半平面交的更多相关文章

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

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

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

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

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

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

  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. JAVA方法中的参数用final来修饰的效果

    很多人都说在JAVA中用final来修饰方法参数的原因是防止方法参数在调用时被篡改,其实也就是这个原因,但理解起来可能会有歧义,我们需要注意的是,在final修饰的方法参数中,如果修饰的是基本类型,那 ...

  2. [转]RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较

    RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...

  3. PHP函数(五)-回调函数

    回调函数是指调用函数的时候将另一个函数作为参数传递到调用的函数中,而不是传递一个普通的变量作为参数 使用回调函数是为了可以将一段自己定义的功能传到函数内部使用 声明回调函数的方法 变量函数声明 < ...

  4. 球的移动(move)

    有n个盒子(1<=N<=1000)围成一个圈,每个盒子有ai个球,所有盒子的球的总数小于等于n.每一次移动,可以把一个球移动到它的一个相邻的盒子内.现在要使得每个盒子的球数<=1,求 ...

  5. oracle 密码默认180天过期

    alter profile default limit password_life_time unlimited; alter user username identified by 'pwd';

  6. LAMP 2.1Apache不记录指定文件类型日志

    访问日志只需要记地址,不用记录图片. 对无用的图片日志做标记,针对标记做限制.打开 vim /usr/local/apache2/conf/extra/httpd-vhosts.conf 把 Erro ...

  7. @SuppressWarnings("unused")注解的作用

    JDK5.0后的新特性,你在使用IDE如eclipse的时候,当你定义了一个变量如int a=0;但是你后面根本就没有使用到这个变量,这一行的前面会有一个黄色的警告标志,你将鼠标移动到上面会提示“这个 ...

  8. Quartz_1_简单编程式任务调度使用(SimpleTrigger)

    最近在工作中,要做定时任务的更能,最开始的时候,想到的是 JavaSE 中,自带 Timer 及 TimerTask 联合使用,完成定时任务.最后发现,随着业务的复杂,JDK 中的 Timer 和 T ...

  9. [hdu3949]XOR(线性基求xor第k小)

    题目大意:求xor所有值的第k小,线性基模板题. #include<cstdio> #include<cstring> #include<algorithm> #i ...

  10. javascript字符串 转 驼峰字符

    字符串  转  驼峰字符 <script type="text/javascript"> var str = 'peng-hui-datou'; function a( ...