洛谷

题意:逆时针给出\(n(n<=10)\)个凸多边形的顶点坐标,求它们交的面积。

学长博客,计算几何知识全面

半平面交问题详细讲解

其他模板题推荐

[ICPC2020 WF] Domes

[CTSC1998]监视摄像机

[ZJOI2008]瞭望塔

[JLOI2013]赛车

还有一些前置知识。两向量\((x_1,y_1),(x_2,y_2)\)的叉乘为\(x_1y_2-x_2y_1\),结果为正说明向量\((x_2,y_2)\)在向量\((x_1,y_1)\)逆时针方向,结果为负则在顺时针方向。求两直线交点的公式如下图所示:

代码与原博客稍有不同。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
char ch = getchar(); int x = 0, f = 1;
while (ch < '0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
const int N = 1e3 + 10;
const double EPS = 1e-5;
int T, tot;
struct node {//一个点,两个坐标
double x, y;
};
node p[15][55];
node ppx[N];
node operator - (node a, node b) {//两个点相减,得到向量ab
node t;
t.x = a.x - b.x;
t.y = a.y - b.y;
return t;
}
double operator ^ (node a, node b) { return a.x * b.y - a.y * b.x; }
//这里的ab应该是向量,然后求叉乘
struct Line {//一个向量,起点s,终点e
node s, e;
};
Line L[N], que[N];
double getAngle(node a) { return atan2(a.y, a.x); }//这里的a应该是向量
double getAngle(Line a) { return atan2(a.e.y - a.s.y, a.e.x - a.s.x); }//求向量a的arctan值
bool cmp(Line a, Line b) {//对所有向量进行极角排序
double A = getAngle(a);
double B = getAngle(b);
return A < B;
}
node getIntersectPoint(Line a, Line b) {//求两直线交点
double a1 = a.s.y - a.e.y, b1 = a.s.x - a.e.x, c1 = 1.0 * a.s.x * a.e.y - 1.0 * a.e.x * a.s.y;
double a2 = b.s.y - b.e.y, b2 = b.s.x - b.e.x, c2 = 1.0 * b.s.x * b.e.y - 1.0 * b.e.x * b.s.y;
node t;
t.x = (1.0 * c1 * b2 - 1.0 * c2 * b1) / (1.0 * a2 * b1 - 1.0 * a1 * b2);
t.y = (1.0 * c1 * a2 - 1.0 * c2 * a1) / (1.0 * a2 * b1 - 1.0 * a1 * b2);
return t;
}
//判断向量a是否在向量bc交点的右侧
bool onRight(Line a, Line b, Line c) {
node o = getIntersectPoint(b, c);
if (((a.e - a.s) ^ (o - a.s)) < 0) return true;//可以自己画图a.s a.e o三个点
return false;
}
double HalfPlaneIntersection() {
sort(L + 1, L + tot + 1, cmp);
int head = 1, tail = 1;
que[1] = L[1];//构造双端队列
for (int i = 2; i <= tot; i++) {
while (head < tail && onRight(L[i], que[tail], que[tail - 1])) tail--;
while (head < tail && onRight(L[i], que[head], que[head + 1])) head++;
que[++tail] = L[i];
//极角相同的向量,保留靠左的那一个
if (fabs(getAngle(que[tail]) - getAngle(que[tail - 1])) < EPS) {
tail--;
if (((que[tail].e - que[tail].s) ^ (L[i].e - que[tail].s)) > EPS)que[tail] = L[i];
}
}
while (head < tail && onRight(que[head], que[tail], que[tail - 1])) tail--;
while (head < tail && onRight(que[tail], que[head], que[head + 1])) head++;
if (tail - head < 2) return 0;//剩下的直线无法构成多边形
double ans = 0;
int tot_jd = 0;
for (int i = head; i < tail; ++i) {
ppx[++tot_jd] = getIntersectPoint(que[i], que[i + 1]);
}
ppx[++tot_jd] = getIntersectPoint(que[tail], que[head]);
for (int i = 2; i < tot_jd; ++i) {
double x1 = ppx[1].x, y1 = ppx[1].y;
double x2 = ppx[i].x, y2 = ppx[i].y;
double x3 = ppx[i + 1].x, y3 = ppx[i + 1].y;
ans = ans + (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1);
}
return ans / 2.0;
}
int main() {
int T; cin >> T;
for (int t = 1; t <= T; ++t) {
int n; cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> p[t][i].x;
cin >> p[t][i].y;
}
for (int i = 1; i < n; i++) {
L[++tot].s.x = p[t][i].x;
L[tot].s.y = p[t][i].y;
L[tot].e.x = p[t][i + 1].x;
L[tot].e.y = p[t][i + 1].y;
}
L[++tot].s.x = p[t][n].x;
L[tot].s.y = p[t][n].y;
L[tot].e.x = p[t][1].x;
L[tot].e.y = p[t][1].y;
}
printf("%.3lf\n", HalfPlaneIntersection());
return 0;
}

[CQOI2006]凸多边形 /【模板】半平面交的更多相关文章

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

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

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

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

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

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

  4. POJ3525 半平面交

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

  5. bzoj 3190 赛车 半平面交

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

  6. poj3335 半平面交

    题意:给出一多边形.判断多边形是否存在一点,使得多边形边界上的所有点都能看见该点. sol:在纸上随手画画就可以找出规律:按逆时针顺序连接所有点.然后找出这些line的半平面交. 题中给出的点已经按顺 ...

  7. POJ 3130 How I Mathematician Wonder What You Are! /POJ 3335 Rotating Scoreboard 初涉半平面交

    题意:逆时针给出N个点,求这个多边形是否有核. 思路:半平面交求多边形是否有核.模板题. 定义: 多边形核:多边形的核可以只是一个点,一条直线,但大多数情况下是一个区域(如果是一个区域则必为 ).核内 ...

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

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

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

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

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

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

随机推荐

  1. vue动态绑定类名

    <view :class="[index == 0 ? 'bgpvip' : 'bgsvip' ,bg]"> 1.class前面需要加: 2.多个类名可以使用数组的方式 ...

  2. 0624.python入门

    课堂笔记 一 编程语言 什么是编程语言? 上面提及的能够被计算机所识别的表达方式即编程语言,语言是沟通的介质,而编程语言是程序员与计算机沟通的介质.在编程的世界里,计算机更像是人的奴隶,人类编程的目的 ...

  3. Vue 项目中实现的微信、微博、QQ空间分享功能(亲测有效)

    需求:文章添加分享功能(包括微信.微博.QQ空间) 如下图所示: 点击图标分别跳转到如下界面:(实现效果如下) 话不多说直接代码(可以封装成组件) <template> <div c ...

  4. fastlane iOS打包 安装与使用

    1.安装 fastlane sudo gem install fastlane 2.进入工程目录下 终端输入 fastlane init 接着输入3 然后control + c退出 接着编写 Fast ...

  5. 初识swoole

    环境: 腾讯云服务器  centos7 在安装完swoole服务之后 使用 php -m  查看是否有该组件 确认存在后 在根目录下 创建一个文件夹 当做专门测试swoole使用 如 8 在该文件夹下 ...

  6. C# 三层架构 简单清晰讲解

    https://www.cnblogs.com/smbk/p/5339610.html

  7. IIS7无法访问.apk文件的解决方法

    随着智能手机的普及,越来越多的人使用手机上网,很多网站也应手机上网的需要推出了网站客户端,.apk文件就是安卓(Android)的应用程序后缀名,默认情况下,使用IIS作为Web服务器的无法访问下载此 ...

  8. 处理Android的物理后退按钮

    在文章.聊天.联系.相册四个页面时,用户点击Android 物理键返回,需要直接退出程序.我这里处理很简单,直接使用react-navigation的属性backbehavior就很快的解决了. &l ...

  9. VS2010查看DLL导出函数的方法

    在window下查看动态库的导出函数可以用vs自带的Dependenc工具:对于VC6.0,VC所带的Depends软件,在VC6安装目录下的tools文件夹里面,可以直接运行. VS2010中没有了 ...

  10. moduleNotFoundError:No module named 'exceptions'

    如果pip install docx 过请先卸载,输入如下指令: pip uninstall docx 方法一: pip install python-docx 方法二: 下载: python_doc ...