首页 > 其他分享 >[CQOI2006]凸多边形 /【模板】半平面交

[CQOI2006]凸多边形 /【模板】半平面交

时间:2022-10-17 23:12:00浏览次数:78  
标签:head int 凸多边形 tot tail que ppx CQOI2006 模板

洛谷

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

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

半平面交问题详细讲解

还有一些前置知识。两向量\((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;
}

标签:head,int,凸多边形,tot,tail,que,ppx,CQOI2006,模板
From: https://www.cnblogs.com/PPXppx/p/16801093.html

相关文章

  • 2022下半年 Acwing 第一篇:快排模板
    模板内容:C++voidquick(intq[],intl,intr){if(l>=r)return;intx=q[(l+r+1)>>1],i=l-1,j=r+1;while(i<j){doi++;while(q[i]<x);......
  • 【Nuxt3从入门到实战】第三啪:巧用布局模板,高效开发从这里开始!
    前言大家好,我是村长,欢迎关注我的公众号村长学前端和B站Young村长!上一篇写了nuxt3路由系统,我们试用了两个重要功能:​​动态路由​​​和​​嵌套路由​​。体验便捷的同时,当......
  • 【模板】快速数论变换
    依旧是常数很大的板子。在H_Kaguya改动之前,达到了\(2.61\,s\)的绝望时间现在好多了,\(1.10\,s\)。(内存不连续访问我会记你一辈子的)#include<iostream>charch;sho......
  • P5788 【模板】单调栈
    【模板】单调栈题目描述给出项数为\(n\)的整数数列\(a_{1\dotsn}\)。定义函数\(f(i)\)代表数列中第\(i\)个元素之后第一个大于\(a_i\)的元素的下标,即\(f(i)......
  • thymeleaf模板引擎,公共代码片段
        Expressionvaria钩去掉  集成 配置                                 ......
  • 【ES6】模板字符串、简化对象写法、箭头函数
    ......
  • QFramework v1.0 使用指南 工具篇:09. SingletonKit 单例模板套件
    SingletonKit是QFramework的第一个收集的工具,经过了7年的迭代,现在已经非常成熟了。好久不见!之前想着让各位直接用QFramework,但是后来想想,如果正在进行的项目直接使......
  • 二、模板语法 数据绑定
    模板语法Vue模板语法包括两大类1、插值语法功能:用于解析标签体内容写法:{{xxx}},xxx是js表达式,可以直接读取到data中的所有区域2、指令语法功能:用于解析标签(包括......
  • 【模板】AVL树
    据说啊,AVL树是第一种被发明的平衡树。它在动态维护过程中,保证了左右子树高度差不超过\(1\),所以说是一种严格平衡的二叉查找树。最重要的就是左旋、右旋以及左右旋、......
  • 在运行时创建一个对话框模板
    在之前的系列文章中,我们花了很长一段时间来学习了对话框模板和对话框管理器。现在,让我们将之前所需到的各个知识点融合一下,来做一些有意思的事情,例如:在程序运行期间创建一......